diff --git a/app/src/main/java/com/example/lexilearn/ui/views/pQuiz/QuizScreen.kt b/app/src/main/java/com/example/lexilearn/ui/views/pQuiz/QuizScreen.kt index 2655bbd..6e9dec5 100644 --- a/app/src/main/java/com/example/lexilearn/ui/views/pQuiz/QuizScreen.kt +++ b/app/src/main/java/com/example/lexilearn/ui/views/pQuiz/QuizScreen.kt @@ -31,20 +31,21 @@ import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import com.example.lexilearn.data.model.MaterialDataModel import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.size import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.VolumeUp import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Surface import androidx.compose.runtime.livedata.observeAsState -import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateMapOf import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.Dp @@ -52,8 +53,6 @@ import androidx.compose.ui.unit.IntOffset import androidx.constraintlayout.compose.ConstraintLayout import com.example.lexilearn.R import com.example.lexilearn.data.model.QuestionType -import com.example.lexilearn.domain.models.ModelAnswerRead -import com.example.lexilearn.ui.components.ButtonNext import com.example.lexilearn.ui.components.CardQuiz import com.example.lexilearn.ui.components.DraggableAnswerCard import com.example.lexilearn.ui.components.FirebaseImage @@ -65,7 +64,6 @@ import com.google.accompanist.flowlayout.FlowRow import com.google.accompanist.flowlayout.MainAxisAlignment import kotlin.math.roundToInt -@OptIn(ExperimentalLayoutApi::class) @Composable fun QuizScreen( navController: NavController, @@ -73,12 +71,22 @@ fun QuizScreen( quizViewModel: QuizViewModel = viewModel() ) { val question by quizViewModel.currentQuestion.collectAsState() + val isButtonVisible by quizViewModel.isButtonVisible val isAnswerCorrect by quizViewModel.isAnswerCorrect.collectAsState() val isTTSInitialized = quizViewModel.isTTSInitialized.observeAsState(false) + val snackbarMessage by quizViewModel.snackbarMessage.collectAsState() + val snackbarHostState = remember { SnackbarHostState() } + LaunchedEffect(Unit) { quizViewModel.loadRandomQuestion(material) } + LaunchedEffect(snackbarMessage) { + snackbarMessage?.let { message -> + snackbarHostState.showSnackbar(message) + quizViewModel.onSnackbarShown() + } + } var rectColumnAnswer by remember { mutableStateOf(Rect.Zero) } @@ -92,25 +100,6 @@ fun QuizScreen( val dataQuiz by quizViewModel.questionShuffled.collectAsState() val listAnswer by quizViewModel.shuffledAnswerLetters.collectAsState() -// var dataQuiz = remember { -// mutableStateListOf( -// ModelSpell(1, true, "? ", showCard = false), -// ModelSpell(2, true, "?", showCard = false), -// ModelSpell(3, true, "?", showCard = false), -// ModelSpell(4, true, "?", showCard = false), -// ) -// } - -// val listAnswer = -// remember { -// mutableStateListOf( -// ModelAnswerRead(1, "a"), -// ModelAnswerRead(2, "c"), -// ModelAnswerRead(3, "d"), -// ModelAnswerRead(4, "k") -// ) -// } - val quizXOffset = remember { mutableStateMapOf() } @@ -139,530 +128,311 @@ fun QuizScreen( mutableStateMapOf() } - Surface(modifier = Modifier.fillMaxSize()) { - GradientQuiz( - navController = navController, - headerText = stringResource(id = R.string.spelltitle), - modifier = Modifier.fillMaxSize() - ) { - ConstraintLayout { - val buttonRef = createRef() - Column( - modifier = Modifier.fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.End, + Scaffold( + snackbarHost = { SnackbarHost(hostState = snackbarHostState) } + ){innerPadding-> + Surface(modifier = Modifier.fillMaxSize().padding(innerPadding)) { + GradientQuiz( + navController = navController, + headerText = stringResource(id = R.string.spelltitle), + modifier = Modifier.fillMaxSize() + ) { + ConstraintLayout { + val buttonRef = createRef() + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, ) { - Text( - "Level: 3", - modifier = Modifier.padding(22.dp), - fontWeight = FontWeight.SemiBold, - fontSize = 18.sp, - color = ctextWhite - ) - } - MyShadowCard( - modifier = Modifier - .padding(12.dp) - .fillMaxWidth() - ) { - Column( + Row( modifier = Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally + horizontalArrangement = Arrangement.End, ) { - Spacer(modifier = Modifier.height(12.dp)) -// Text( -// text = "Susun Kata", -// fontSize = 20.sp, -// fontWeight = FontWeight.Bold -// ) -// Spacer(modifier = Modifier.height(12.dp)) -// Image( -// painter = painterResource(id = R.drawable.ic_news), -// contentDescription = "image", -// modifier = Modifier.size(120.dp) -// ) - if (question != null) { - if (question?.questionType == QuestionType.IMAGE) { - FirebaseImage( - path = question!!.question, - contentScale = ContentScale.Crop, - modifier = Modifier.size(200.dp) - ) - - } else if (question?.questionType == QuestionType.TEXT) { - Text( - text = question!!.question, - fontSize = 20.sp, - fontWeight = FontWeight.Bold, - modifier = Modifier.padding(12.dp) - ) - } else if (question?.questionType == QuestionType.AUDIO) { - IconButton( - onClick = { - quizViewModel.speakLetter(question!!.question) - }, - modifier = Modifier - .size(160.dp) - - ) { - Icon( - imageVector = Icons.Filled.VolumeUp, // 🔥 Ikon Speaker dari Material Icons - contentDescription = "Speaker Icon", - tint = Color.Black // 🔥 Warna ikon + Text( + "", + modifier = Modifier.padding(22.dp), + fontWeight = FontWeight.SemiBold, + fontSize = 18.sp, + color = ctextWhite + ) + } + MyShadowCard( + modifier = Modifier + .padding(12.dp) + .fillMaxWidth() + ) { + Column( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Spacer(modifier = Modifier.height(12.dp)) + if (question != null) { + if (question?.questionType == QuestionType.IMAGE) { + FirebaseImage( + path = question!!.question, + contentScale = ContentScale.Crop, + modifier = Modifier.size(160.dp) ) + } else if (question?.questionType == QuestionType.TEXT) { + Text( + text = question!!.question, + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(12.dp) + ) + } else if (question?.questionType == QuestionType.AUDIO) { + IconButton( + onClick = { + quizViewModel.speakLetter(question!!.question) + }, + ) { + Icon( + imageVector = Icons.Filled.VolumeUp, + contentDescription = "Speaker Icon", + tint = Color.Black, + modifier = Modifier.size(200.dp) + ) + } } } - } + Spacer(modifier = Modifier.height(12.dp)) + FlowRow( + mainAxisSpacing = 8.dp, + crossAxisSpacing = 8.dp, + mainAxisAlignment = MainAxisAlignment.Center, + modifier = Modifier + .fillMaxWidth() + .padding(12.dp) - Spacer(modifier = Modifier.height(12.dp)) -// Row( -// modifier = Modifier.fillMaxWidth(), -// horizontalArrangement = Arrangement.SpaceAround -// ) { -// dataQuiz.forEach { dt -> -// val id = dt.id -// if (!boxRectDragable.containsKey(id)) -// boxRectDragable[id] = Rect.Zero -// if (!boxRectQuiz.containsKey(id)) -// boxRectQuiz[id] = Rect.Zero -// if (!quizXOffset.containsKey(id)) -// quizXOffset[id] = 0f -// if (!quizYOffset.containsKey(id)) -// quizYOffset[id] = 0f -// CardQuiz( -// modifier = Modifier -// .padding(vertical = 10.dp) -// .size(minSize) -// .onGloballyPositioned { coordinates -> -// if (dt.type) -// boxRectQuiz[id] = coordinates.boundsInWindow() -// } -// ) { -// if (dt.type) { -// Text( -// text = dt.data, // Use the state to display text -// color = ctextWhite, -// fontWeight = FontWeight.Bold, -// textAlign = TextAlign.Center, -// modifier = Modifier.fillMaxWidth() -// ) -// if (dt.showCard) { -// DraggableAnswerCard( -// item = dt.data, -// modifier = Modifier -// .offset { -// val xOffset = quizXOffset[id] ?: 0f -// val yOffset = quizYOffset[id] ?: 0f -// IntOffset( -// xOffset.roundToInt(), -// yOffset.roundToInt() -// ) -// } -// .onGloballyPositioned { -// boxRectDragable[id] = -// it.boundsInWindow() -// } -// .fillMaxSize() -// .pointerInput(Unit) { -// detectDragGestures( -// onDrag = { change, dragAmount -> -// change.consume() -// quizXOffset[id] = -// quizXOffset[id]!! + dragAmount.x -// quizYOffset[id] = -// quizYOffset[id]!! + dragAmount.y -// }, -// onDragEnd = { -// var checkNull = false -// for ((ind, entry) in boxRectQuiz.entries.withIndex()) { -// val (key, rect) = entry -// if (key == id) -// continue -// -// if (dataQuiz[ind].hasContent) -// continue -// -// if (boxRectDragable[id]!!.overlaps( -// rect -// ) -// ) { -// quizViewModel.updateQuestionShuffled( -// ind, -// dt -// ) -//// dataQuiz = -//// dataQuiz.apply { -//// this[ind] = -//// this[ind].copy( -//// data = dt.data, -//// showCard = true, -//// emp = dt.emp, -//// hasContent = true -//// ) -//// } -// dt.apply { -// hasContent = false -// showCard = false -// data = "?" -// } -// checkNull = true -// quizXOffset[id] = 0f -// quizYOffset[id] = 0f -// break -// } -// -// } -// if (boxRectDragable[id]!!.overlaps( -// rectColumnAnswer -// ) -// ) { -// val emDt = dt.emp -// if (emDt != null) { -// dt.apply { -// hasContent = false -// showCard = false -// data = "?" -// } -// checkNull = true -// cardSize[emDt] = maxSize -// quizXOffset[id] = 0f -// quizYOffset[id] = 0f -// dt.data = "?" -// } -// } -// if (!checkNull) { -// quizXOffset[id] = 0f -// quizYOffset[id] = 0f -// } -// } -// ) -// } -// ) -// } -// } else { -// Box(modifier = Modifier.align(Alignment.CenterVertically)) { -// Text( -// text = dt.data, -// color = ctextWhite, -// fontSize = 20.sp, -// fontWeight = FontWeight.Bold, -// textAlign = TextAlign.Center, -// ) -// } -// -// } -// } -// } -// } - FlowRow( - modifier = Modifier.fillMaxWidth().padding(12.dp), - mainAxisSpacing = 8.dp, // Jarak horizontal antar item - crossAxisSpacing = 8.dp, // Jarak vertikal antar item - mainAxisAlignment = MainAxisAlignment.Center - ) { - dataQuiz.forEach { dt -> - val id = dt.id - if (!boxRectDragable.containsKey(id)) - boxRectDragable[id] = Rect.Zero - if (!boxRectQuiz.containsKey(id)) - boxRectQuiz[id] = Rect.Zero - if (!quizXOffset.containsKey(id)) - quizXOffset[id] = 0f - if (!quizYOffset.containsKey(id)) - quizYOffset[id] = 0f + ) { + dataQuiz.forEach { dt -> + val id = dt.id + if (!boxRectDragable.containsKey(id)) + boxRectDragable[id] = Rect.Zero + if (!boxRectQuiz.containsKey(id)) + boxRectQuiz[id] = Rect.Zero + if (!quizXOffset.containsKey(id)) + quizXOffset[id] = 0f + if (!quizYOffset.containsKey(id)) + quizYOffset[id] = 0f - CardQuiz( - modifier = Modifier - .padding(vertical = 10.dp) - .size(minSize) - .onGloballyPositioned { coordinates -> - if (dt.type) - boxRectQuiz[id] = coordinates.boundsInWindow() - } - ) { - if (dt.type) { - Text( - text = dt.data, - color = ctextWhite, - fontWeight = FontWeight.Bold, - textAlign = TextAlign.Center, - modifier = Modifier.fillMaxWidth() - ) - if (dt.showCard) { - DraggableAnswerCard( - item = dt.data, - modifier = Modifier - .offset { - val xOffset = quizXOffset[id] ?: 0f - val yOffset = quizYOffset[id] ?: 0f - IntOffset( - xOffset.roundToInt(), - yOffset.roundToInt() - ) - } - .onGloballyPositioned { - boxRectDragable[id] = it.boundsInWindow() - } - .fillMaxSize() - .pointerInput(Unit) { - detectDragGestures( - onDrag = { change, dragAmount -> - change.consume() - quizXOffset[id] = - quizXOffset[id]!! + dragAmount.x - quizYOffset[id] = - quizYOffset[id]!! + dragAmount.y - }, - onDragEnd = { - var checkNull = false - for ((ind, entry) in boxRectQuiz.entries.withIndex()) { - val (key, rect) = entry - if (key == id) - continue - - if (dataQuiz[ind].hasContent) - continue - - if (boxRectDragable[id]!!.overlaps(rect)) { - quizViewModel.updateQuestionShuffled(ind, dt) - dt.apply { - hasContent = false - showCard = false - data = "?" - } - checkNull = true - quizXOffset[id] = 0f - quizYOffset[id] = 0f - break - } - } - if (boxRectDragable[id]!!.overlaps(rectColumnAnswer)) { - val emDt = dt.emp - if (emDt != null) { - dt.apply { - hasContent = false - showCard = false - data = "?" - } - checkNull = true - cardSize[emDt] = maxSize - quizXOffset[id] = 0f - quizYOffset[id] = 0f - dt.data = "?" - } - } - if (!checkNull) { - quizXOffset[id] = 0f - quizYOffset[id] = 0f - } - } - ) - } - ) - } - } else { - Box(modifier = Modifier) { + CardQuiz( + modifier = Modifier + .padding(vertical = 10.dp) + .size(minSize) + .onGloballyPositioned { coordinates -> + if (dt.type) + boxRectQuiz[id] = coordinates.boundsInWindow() + } + ) { + if (dt.type) { Text( text = dt.data, color = ctextWhite, - fontSize = 20.sp, fontWeight = FontWeight.Bold, textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth() ) + if (dt.showCard) { + DraggableAnswerCard( + item = dt.data, + modifier = Modifier + .offset { + val xOffset = quizXOffset[id] ?: 0f + val yOffset = quizYOffset[id] ?: 0f + IntOffset( + xOffset.roundToInt(), + yOffset.roundToInt() + ) + } + .onGloballyPositioned { + boxRectDragable[id] = + it.boundsInWindow() + } + .fillMaxSize() + .pointerInput(Unit) { + detectDragGestures( + onDrag = { change, dragAmount -> + change.consume() + quizXOffset[id] = + quizXOffset[id]!! + dragAmount.x + quizYOffset[id] = + quizYOffset[id]!! + dragAmount.y + }, + onDragEnd = { + var checkNull = false + for ((ind, entry) in boxRectQuiz.entries.withIndex()) { + val (key, rect) = entry + if (key == id) + continue + + if (dataQuiz[ind].hasContent) + continue + + if (boxRectDragable[id]!!.overlaps( + rect + ) + ) { + quizViewModel.updateQuestionShuffled( + ind, + dt + ) + dt.apply { + hasContent = false + showCard = false + data = "?" + } + checkNull = true + quizXOffset[id] = 0f + quizYOffset[id] = 0f + break + } + } + if (boxRectDragable[id]!!.overlaps( + rectColumnAnswer + ) + ) { + val emDt = dt.emp + if (emDt != null) { + dt.apply { + hasContent = false + showCard = false + data = "?" + } + checkNull = true + cardSize[emDt] = maxSize + quizXOffset[id] = 0f + quizYOffset[id] = 0f + dt.data = "?" + } + } + if (!checkNull) { + quizXOffset[id] = 0f + quizYOffset[id] = 0f + } + } + ) + } + ) + } + } else { + Box(modifier = Modifier) { + Text( + text = dt.data, + color = ctextWhite, + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + textAlign = TextAlign.Center, + ) + } } } } } + Spacer(modifier = Modifier.height(12.dp)) } - Spacer(modifier = Modifier.height(12.dp)) } - } - Spacer(modifier = Modifier.height(12.dp)) - Spacer( - modifier = Modifier - .fillMaxWidth() - .height(1.dp) - .background(ctextGray) - ) - Spacer(modifier = Modifier.height(12.dp)) - Column( - modifier = Modifier - .fillMaxWidth() - .onGloballyPositioned { - rectColumnAnswer = it.boundsInWindow() - }, - ) { - listAnswer.chunked(2).forEach { rowItems -> - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.Center - ) { - rowItems.forEach { item -> - val id = item.id - if (!cardSize.containsKey(id)) - cardSize[id] = maxSize - if (!boxRectAnswer.containsKey(id)) - boxRectAnswer[id] = Rect.Zero - if (!answerXOffset.containsKey(id)) - answerXOffset[id] = 0f - if (!answerYOffset.containsKey(id)) - answerYOffset[id] = 0f - DraggableAnswerCard( - item = item.data, - modifier = Modifier - .padding(10.dp) - .size(cardSize[id]!!) - .offset { - IntOffset( - answerXOffset[id]!!.roundToInt(), - answerYOffset[id]!!.roundToInt() - ) - } - .onGloballyPositioned { coordinates -> - boxRectAnswer[id] = coordinates.boundsInWindow() - } - .pointerInput(Unit) { - detectDragGestures( - onDrag = { change, dragAmount -> - change.consume() - answerXOffset[id] = - answerXOffset[id]!! + dragAmount.x - answerYOffset[id] = - answerYOffset[id]!! + dragAmount.y - cardSize[id] = minSize - }, - onDragEnd = { - var checkNull = false - for ((ind, entry) in boxRectQuiz.entries.withIndex()) { - val (_, rect) = entry - if (dataQuiz[ind].hasContent) - continue + Spacer(modifier = Modifier.height(12.dp)) + Spacer( + modifier = Modifier + .fillMaxWidth() + .height(1.dp) + .background(ctextGray) + ) + Spacer(modifier = Modifier.height(12.dp)) + Column( + modifier = Modifier + .fillMaxWidth() + .heightIn(min = 300.dp) + .onGloballyPositioned { + rectColumnAnswer = it.boundsInWindow() + }, + ) { + listAnswer.chunked(3).forEach { rowItems -> + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + rowItems.forEach { item -> + val id = item.id + if (!cardSize.containsKey(id)) + cardSize[id] = maxSize + if (!boxRectAnswer.containsKey(id)) + boxRectAnswer[id] = Rect.Zero + if (!answerXOffset.containsKey(id)) + answerXOffset[id] = 0f + if (!answerYOffset.containsKey(id)) + answerYOffset[id] = 0f + DraggableAnswerCard( + item = item.data, + modifier = Modifier + .padding(4.dp) + .size(cardSize[id]!!) + .offset { + IntOffset( + answerXOffset[id]!!.roundToInt(), + answerYOffset[id]!!.roundToInt() + ) + } + .onGloballyPositioned { coordinates -> + boxRectAnswer[id] = coordinates.boundsInWindow() + } + .pointerInput(Unit) { + detectDragGestures( + onDrag = { change, dragAmount -> + change.consume() + answerXOffset[id] = + answerXOffset[id]!! + dragAmount.x + answerYOffset[id] = + answerYOffset[id]!! + dragAmount.y + cardSize[id] = minSize + }, + onDragEnd = { + var checkNull = false + for ((ind, entry) in boxRectQuiz.entries.withIndex()) { + val (_, rect) = entry + if (dataQuiz[ind].hasContent) + continue - if (boxRectAnswer[id]!!.overlaps( - rect - ) - ) { - cardSize[id] = minSize - quizViewModel.updateQuestionShuffled( - ind, - dataQuiz[ind].copy(data = item.data, showCard = true, emp = id, hasContent = true) - ) -// dataQuiz = dataQuiz -// .apply { -// this[ind] = -// this[ind].copy( -// data = item.data, -// showCard = true, -// emp = id, -// hasContent = true -// ) -// } - checkNull = true - cardSize[id] = 0.dp + if (boxRectAnswer[id]!!.overlaps( + rect + ) + ) { + cardSize[id] = minSize + quizViewModel.updateQuestionShuffled( + ind, + dataQuiz[ind].copy( + data = item.data, + showCard = true, + emp = id, + hasContent = true + ) + ) + checkNull = true + cardSize[id] = 0.dp + answerXOffset[id] = 0f + answerYOffset[id] = 0f + break + } + } + if (!checkNull) { + cardSize[id] = maxSize answerXOffset[id] = 0f answerYOffset[id] = 0f - break } } - if (!checkNull) { - cardSize[id] = maxSize - answerXOffset[id] = 0f - answerYOffset[id] = 0f - } - } - ) - } - ) + ) + } + ) + } } } } + Spacer(modifier = Modifier.height(12.dp)) } - Spacer(modifier = Modifier.height(12.dp)) + } - - ButtonNext( - onclick = { - navController.navigate("write") - }, - text = stringResource(id = R.string.next), - painter = painterResource(id = R.drawable.ic_next), - modifier = Modifier - .padding(vertical = 30.dp, horizontal = 50.dp) - .fillMaxWidth() - .constrainAs(buttonRef) { - bottom.linkTo(parent.bottom) - } - ) } - } - } -} -// -//@Composable -//fun DragAndDropAnswer(correctAnswer: String, onAnswerSubmitted: (String) -> Unit) { -// val shuffledLetters = correctAnswer.toList().shuffled() -// -// var selectedLetters by remember { mutableStateOf("") } -// val answerBoxRect = remember { mutableStateOf(Rect.Zero) } -// -// Column( -// modifier = Modifier.fillMaxWidth(), -// horizontalAlignment = Alignment.CenterHorizontally -// ) { -// Box( -// modifier = Modifier -// .size(150.dp, 50.dp) -// .background(Color.LightGray) -// .onGloballyPositioned { answerBoxRect.value = it.boundsInWindow() }, -// contentAlignment = Alignment.Center -// ) { -// Text(text = selectedLetters, fontSize = 20.sp) -// } -// -// Spacer(modifier = Modifier.height(20.dp)) -// -// Row { -// shuffledLetters.forEach { letter -> -// DraggableLetter( -// letter = letter.toString(), -// onDrop = { -// selectedLetters += letter -// if (selectedLetters.length == correctAnswer.length) { -// onAnswerSubmitted(selectedLetters) -// } -// } -// ) -// } -// } -// } -//} -// -//@Composable -//fun DraggableLetter(letter: String, onDrop: () -> Unit) { -// var offsetX by remember { mutableStateOf(0f) } -// var offsetY by remember { mutableStateOf(0f) } -// -// Box( -// modifier = Modifier -// .size(50.dp) -// .background(Color.Blue) -// .pointerInput(Unit) { -// detectDragGestures( -// onDrag = { change, dragAmount -> -// change.consume() -// offsetX += dragAmount.x -// offsetY += dragAmount.y -// }, -// onDragEnd = { onDrop() } -// ) -// }, -// contentAlignment = Alignment.Center -// ) { -// Text(text = letter, fontSize = 20.sp, color = Color.White) -// } -//} \ No newline at end of file + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/lexilearn/ui/views/pQuiz/QuizViewModel.kt b/app/src/main/java/com/example/lexilearn/ui/views/pQuiz/QuizViewModel.kt index f2655dc..af64482 100644 --- a/app/src/main/java/com/example/lexilearn/ui/views/pQuiz/QuizViewModel.kt +++ b/app/src/main/java/com/example/lexilearn/ui/views/pQuiz/QuizViewModel.kt @@ -2,20 +2,26 @@ package com.example.lexilearn.ui.views.pQuiz import android.app.Application import android.speech.tts.TextToSpeech +import android.util.Log +import androidx.compose.runtime.State +import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope import com.example.lexilearn.data.model.MaterialDataModel import com.example.lexilearn.data.model.QuizQuestion import com.example.lexilearn.data.repository.QuizRepository import com.example.lexilearn.domain.models.ModelAnswerRead import com.example.lexilearn.domain.models.ModelSpell +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch import java.util.Locale class QuizViewModel(application: Application) : AndroidViewModel(application), - TextToSpeech.OnInitListener { + TextToSpeech.OnInitListener { private val quizRepository = QuizRepository() private val _currentQuestion = MutableStateFlow(null) @@ -33,25 +39,14 @@ class QuizViewModel(application: Application) : AndroidViewModel(application), private val _shuffledAnswerLetters = MutableStateFlow>(emptyList()) val shuffledAnswerLetters: StateFlow> = _shuffledAnswerLetters -// fun updateShuffledLetter(index: Int, newData: ModelAnswerRead) { -// _shuffledAnswerLetters.value = _shuffledAnswerLetters.value.mapIndexed { i, item -> -// if (i == index) { -// item.copy( -// data = newData.data, -// showCard = true, -// emp = newData.emp, -// hasContent = true -// ) -// } else { -// item -// } -// } -// } private val _questionShuffled = MutableStateFlow>(emptyList()) val questionShuffled: StateFlow> = _questionShuffled + private val _isButtonVisible = mutableStateOf(false) + val isButtonVisible: State get() = _isButtonVisible + fun updateQuestionShuffled(index: Int, newData: ModelSpell) { _questionShuffled.value = _questionShuffled.value.mapIndexed { i, item -> if (i == index) { @@ -69,20 +64,29 @@ class QuizViewModel(application: Application) : AndroidViewModel(application), fun loadRandomQuestion(material: MaterialDataModel) { -// _currentQuestion.value = quizRepository.generateRandomQuestion(material) - _currentQuestion.value = quizRepository.generateQuestion(material, 1, 2) - val dataQuest = _currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char -> - ModelSpell(index + 1, true, "?", showCard = false) - } ?: emptyList() + _currentQuestion.value = quizRepository.generateQuestion(material, 2, 2) + + val dataQuest = + _currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char -> + ModelSpell(index + 1, true, "?", showCard = false) + } ?: emptyList() _questionShuffled.value = dataQuest - val listAnswer = _currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char -> - ModelAnswerRead(index + 1, char.toString()) - } ?: emptyList() - _shuffledAnswerLetters.value = listAnswer - println("testing_question ${_currentQuestion.value}") - println("testing_question ${material}") + + val listAnswer = + _currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char -> + ModelAnswerRead(index + 1, char.toString()) + } ?: emptyList() + val shuflledAnswer = listAnswer.shuffled() + _shuffledAnswerLetters.value = shuflledAnswer + + // Menambahkan delay 1 detik sebelum memanggil observeData() +// viewModelScope.launch { +// delay(1000L) // delay 1 detik +// +// } } + fun submitAnswer(answer: String) { _userAnswer.value = answer _isAnswerCorrect.value = @@ -95,6 +99,7 @@ class QuizViewModel(application: Application) : AndroidViewModel(application), init { tts = TextToSpeech(application, this) + observeData() } override fun onInit(status: Int) { @@ -112,6 +117,48 @@ class QuizViewModel(application: Application) : AndroidViewModel(application), } } + fun checkAnswer(answerString: String): Boolean { + if (answerString == currentQuestion.value?.correctAnswer?.correctWord) { + return true + } + return false + } + + fun observeData() { + viewModelScope.launch { + _questionShuffled.collect { newList -> + // Lakukan aksi setiap kali data berubah + var answerString = "" + newList.forEach { text -> + answerString = answerString + text.data + } + if (answerString.contains("?") || answerString.isEmpty() || answerString.contains("null")) { + _isButtonVisible.value = false + } else { + Log.d("cobaaja", answerString) + val checkData = checkAnswer(answerString); + if (checkData) { + triggerSnackbar("Jawaban Benar") + } else { + triggerSnackbar("Jawaban Salah") + } + _isButtonVisible.value = true + } + } + } + } + + private val _snackbarMessage = MutableStateFlow(null) + val snackbarMessage: StateFlow = _snackbarMessage + + fun triggerSnackbar(message: String) { + _snackbarMessage.value = message + } + + fun onSnackbarShown() { + _snackbarMessage.value = null + } + override fun onCleared() { tts?.stop() tts?.shutdown()