update unlock material
This commit is contained in:
parent
522e568a9e
commit
98474010d0
|
@ -7,9 +7,11 @@ import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.navigation.NavType
|
||||||
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.navArgument
|
||||||
import com.example.lexilearn.data.model.MaterialDataModel
|
import com.example.lexilearn.data.model.MaterialDataModel
|
||||||
import com.example.lexilearn.data.model.UserModel
|
import com.example.lexilearn.data.model.UserModel
|
||||||
import com.example.lexilearn.data.repository.MaterialRepository
|
import com.example.lexilearn.data.repository.MaterialRepository
|
||||||
|
@ -91,6 +93,15 @@ fun MyApp() {
|
||||||
composable("resultscreening") { ResultScreeningScreen(navController) }
|
composable("resultscreening") { ResultScreeningScreen(navController) }
|
||||||
composable("learnAlphabet") { LearnAlphabetScreen(navController) }
|
composable("learnAlphabet") { LearnAlphabetScreen(navController) }
|
||||||
composable("learnNumber") { LearnNumberScreen(navController) }
|
composable("learnNumber") { LearnNumberScreen(navController) }
|
||||||
|
// composable(
|
||||||
|
// "navMaterial/{materialId}",
|
||||||
|
// arguments = listOf(
|
||||||
|
// navArgument("materialId") { type = NavType.StringType }
|
||||||
|
// )
|
||||||
|
// ) { backStackEntry ->
|
||||||
|
// val materialId = backStackEntry.arguments?.getString("materialId") ?: ""
|
||||||
|
// NavMaterialScreen(navController, materialId)
|
||||||
|
// }
|
||||||
composable("navMaterial/{materialId}") { backStackEntry ->
|
composable("navMaterial/{materialId}") { backStackEntry ->
|
||||||
val materialId = backStackEntry.arguments?.getString("materialId")
|
val materialId = backStackEntry.arguments?.getString("materialId")
|
||||||
NavMaterialScreen(navController, materialId ?: "")
|
NavMaterialScreen(navController, materialId ?: "")
|
||||||
|
@ -99,9 +110,11 @@ fun MyApp() {
|
||||||
val materialList = navController.previousBackStackEntry
|
val materialList = navController.previousBackStackEntry
|
||||||
?.savedStateHandle
|
?.savedStateHandle
|
||||||
?.get<List<MaterialDataModel>>("materialList")
|
?.get<List<MaterialDataModel>>("materialList")
|
||||||
|
val indexValue = navController.previousBackStackEntry
|
||||||
|
?.savedStateHandle
|
||||||
|
?.get<Int>("indexValue") ?: -1
|
||||||
if (materialList != null) {
|
if (materialList != null) {
|
||||||
DetailMaterialScreen(navController, materialList)
|
DetailMaterialScreen(navController, materialList, indexValue)
|
||||||
}else{
|
}else{
|
||||||
println("masuk kondisi else")
|
println("masuk kondisi else")
|
||||||
}
|
}
|
||||||
|
@ -111,14 +124,21 @@ fun MyApp() {
|
||||||
?.savedStateHandle
|
?.savedStateHandle
|
||||||
?.get<List<MaterialDataModel>>("selectedMaterialList")
|
?.get<List<MaterialDataModel>>("selectedMaterialList")
|
||||||
|
|
||||||
val selectedMaterial = selectedMaterialList?.firstOrNull()
|
val typeQuiz = navController.previousBackStackEntry
|
||||||
|
?.savedStateHandle
|
||||||
|
?.get<String>("typeQuiz") ?: "default"
|
||||||
|
|
||||||
if (selectedMaterial != null) {
|
val indexValue = navController.previousBackStackEntry
|
||||||
QuizScreen(navController, selectedMaterial)
|
?.savedStateHandle
|
||||||
|
?.get<Int>("indexValue") ?: 0
|
||||||
|
|
||||||
|
if (!selectedMaterialList.isNullOrEmpty()) {
|
||||||
|
QuizScreen(navController, selectedMaterialList, typeQuiz, indexValue)
|
||||||
} else {
|
} else {
|
||||||
Text("Error: Data tidak tersedia")
|
Text("Error: Data tidak tersedia")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// composable("detailMaterial/{materialJson}") { backStackEntry ->
|
// composable("detailMaterial/{materialJson}") { backStackEntry ->
|
||||||
// val jsonMaterial = backStackEntry.arguments?.getString("materialJson")
|
// val jsonMaterial = backStackEntry.arguments?.getString("materialJson")
|
||||||
//
|
//
|
||||||
|
|
|
@ -65,24 +65,27 @@ class MaterialRepository(private val context: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateUnlockData(idUnlock: String, value: Int, callback: (Boolean) -> Unit) {
|
fun updateUnlockData(idUnlock: String, value: Int, callback: (Boolean) -> Unit) {
|
||||||
|
try {
|
||||||
val userId = sharedPrefHelper.getUserId()
|
val userId = sharedPrefHelper.getUserId()
|
||||||
|
|
||||||
if (userId == null) {
|
if (userId == null) {
|
||||||
|
println("printUpdateUnlock: userId is null")
|
||||||
callback(false)
|
callback(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val userRef = FirebaseDatabase.getInstance().getReference("users/$userId/unlock_data/$idUnlock")
|
val userRef = FirebaseDatabase.getInstance().getReference("users/$userId/unlock_data/$idUnlock")
|
||||||
|
|
||||||
// 🔥 Ambil data user dari Firebase
|
// Ambil data user dari Firebase dengan try-catch di dalam callback
|
||||||
userRef.get().addOnSuccessListener { snapshot ->
|
userRef.get().addOnSuccessListener { snapshot ->
|
||||||
|
try {
|
||||||
val currentValue = snapshot.getValue(Int::class.java) ?: 0
|
val currentValue = snapshot.getValue(Int::class.java) ?: 0
|
||||||
|
|
||||||
// 🔥 Hanya update jika nilai baru lebih besar
|
// Hanya update jika nilai baru lebih besar
|
||||||
if (value > currentValue) {
|
if (value > currentValue) {
|
||||||
userRef.setValue(value).addOnCompleteListener { task ->
|
userRef.setValue(value).addOnCompleteListener { task ->
|
||||||
|
try {
|
||||||
if (task.isSuccessful) {
|
if (task.isSuccessful) {
|
||||||
// 🔥 Update juga di SharedPreferences
|
// Update juga di SharedPreferences
|
||||||
val updatedUser = sharedPrefHelper.getUserData()
|
val updatedUser = sharedPrefHelper.getUserData()
|
||||||
updatedUser?.unlock_data?.let { unlockData ->
|
updatedUser?.unlock_data?.let { unlockData ->
|
||||||
when (idUnlock) {
|
when (idUnlock) {
|
||||||
|
@ -92,20 +95,110 @@ class MaterialRepository(private val context: Context) {
|
||||||
"limb" -> unlockData.limb = value
|
"limb" -> unlockData.limb = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sharedPrefHelper.saveUserData(updatedUser!!)
|
// Pastikan updatedUser tidak null sebelum menyimpan
|
||||||
|
if (updatedUser != null) {
|
||||||
|
println("printUpdateUnlock: successfully updated Firebase and SharedPreferences")
|
||||||
|
sharedPrefHelper.saveUserData(updatedUser)
|
||||||
callback(true)
|
callback(true)
|
||||||
} else {
|
} else {
|
||||||
|
println("printUpdateUnlock: updatedUser is null after updating Firebase")
|
||||||
|
callback(false)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println("printUpdateUnlock: task is not successful")
|
||||||
|
callback(false)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
println("printUpdateUnlock: exception in onCompleteListener: $e")
|
||||||
callback(false)
|
callback(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
callback(false) // 🔥 Jika nilai baru <= nilai lama, tidak update
|
println("printUpdateUnlock: new value $value is not greater than current value $currentValue")
|
||||||
|
callback(false) // Jika nilai baru <= nilai lama, tidak update
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
println("printUpdateUnlock: exception in onSuccessListener: $e")
|
||||||
|
callback(false)
|
||||||
}
|
}
|
||||||
}.addOnFailureListener {
|
}.addOnFailureListener {
|
||||||
|
it.printStackTrace()
|
||||||
|
println("printUpdateUnlock: failed to get data: ${it.message}")
|
||||||
|
callback(false)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
println("printUpdateUnlock: error_update_unlock_data: $e")
|
||||||
|
e.printStackTrace()
|
||||||
callback(false)
|
callback(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fun updateUnlockData(idUnlock: String, value: Int, callback: (Boolean) -> Unit) {
|
||||||
|
// try {
|
||||||
|
// val userId = sharedPrefHelper.getUserId()
|
||||||
|
// if (userId == null) {
|
||||||
|
// callback(false)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// val userRef = FirebaseDatabase.getInstance().getReference("users/$userId/unlock_data/$idUnlock")
|
||||||
|
//
|
||||||
|
// // Ambil data user dari Firebase dengan try-catch di dalam callback
|
||||||
|
// userRef.get().addOnSuccessListener { snapshot ->
|
||||||
|
// try {
|
||||||
|
// val currentValue = snapshot.getValue(Int::class.java) ?: 0
|
||||||
|
//
|
||||||
|
// // Hanya update jika nilai baru lebih besar
|
||||||
|
// if (value > currentValue) {
|
||||||
|
// userRef.setValue(value).addOnCompleteListener { task ->
|
||||||
|
// try {
|
||||||
|
// if (task.isSuccessful) {
|
||||||
|
// // Update juga di SharedPreferences
|
||||||
|
// val updatedUser = sharedPrefHelper.getUserData()
|
||||||
|
// updatedUser?.unlock_data?.let { unlockData ->
|
||||||
|
// when (idUnlock) {
|
||||||
|
// "animal" -> unlockData.animal = value
|
||||||
|
// "family" -> unlockData.family = value
|
||||||
|
// "house" -> unlockData.house = value
|
||||||
|
// "limb" -> unlockData.limb = value
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// // Pastikan updatedUser tidak null sebelum menyimpan
|
||||||
|
// if (updatedUser != null) {
|
||||||
|
// sharedPrefHelper.saveUserData(updatedUser)
|
||||||
|
// callback(true)
|
||||||
|
// } else {
|
||||||
|
// callback(false)
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// callback(false)
|
||||||
|
// }
|
||||||
|
// } catch (e: Exception) {
|
||||||
|
// e.printStackTrace()
|
||||||
|
// callback(false)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// callback(false) // Jika nilai baru <= nilai lama, tidak update
|
||||||
|
// }
|
||||||
|
// } catch (e: Exception) {
|
||||||
|
// e.printStackTrace()
|
||||||
|
// callback(false)
|
||||||
|
// }
|
||||||
|
// }.addOnFailureListener {
|
||||||
|
// it.printStackTrace()
|
||||||
|
// callback(false)
|
||||||
|
// }
|
||||||
|
// } catch (e: Exception) {
|
||||||
|
// println("error_update_unlock_data: $e")
|
||||||
|
// e.printStackTrace()
|
||||||
|
// callback(false)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
fun getUnlockValue(idUnlock: String, callback: (Int?) -> Unit) {
|
fun getUnlockValue(idUnlock: String, callback: (Int?) -> Unit) {
|
||||||
val userId = sharedPrefHelper.getUserId()
|
val userId = sharedPrefHelper.getUserId()
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ import com.example.lexilearn.ui.theme.ctextBlack
|
||||||
import com.example.lexilearn.ui.theme.ctextGray
|
import com.example.lexilearn.ui.theme.ctextGray
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DetailMaterialScreen(navController: NavController, materialListData: List<MaterialDataModel>) {
|
fun DetailMaterialScreen(navController: NavController, materialListData: List<MaterialDataModel>, indexValue: Int) {
|
||||||
val viewModel: DetailMaterialViewModel = viewModel()
|
val viewModel: DetailMaterialViewModel = viewModel()
|
||||||
LaunchedEffect(materialListData) {
|
LaunchedEffect(materialListData) {
|
||||||
viewModel.fetchMaterial(materialListData)
|
viewModel.fetchMaterial(materialListData)
|
||||||
|
@ -154,17 +154,19 @@ fun DetailMaterialScreen(navController: NavController, materialListData: List<Ma
|
||||||
}
|
}
|
||||||
ButtonNext(
|
ButtonNext(
|
||||||
onclick = {
|
onclick = {
|
||||||
val selectedMaterial = materialListData.firstOrNull()
|
if (materialListData.isNotEmpty()) {
|
||||||
if (selectedMaterial != null) {
|
|
||||||
// Simpan ke savedStateHandle sebagai List<MaterialDataModel> tapi hanya satu elemen
|
|
||||||
navController.currentBackStackEntry
|
navController.currentBackStackEntry
|
||||||
?.savedStateHandle
|
?.savedStateHandle
|
||||||
?.set("selectedMaterialList", listOf(selectedMaterial))
|
?.set("selectedMaterialList", viewModel.randomMaterialModel())
|
||||||
|
navController.currentBackStackEntry
|
||||||
// Navigasi ke QuizScreen
|
?.savedStateHandle
|
||||||
|
?.set("typeQuiz", materialListData[0].category)
|
||||||
|
navController.currentBackStackEntry
|
||||||
|
?.savedStateHandle
|
||||||
|
?.set("indexValue", indexValue)
|
||||||
navController.navigate("quizScreen")
|
navController.navigate("quizScreen")
|
||||||
}
|
}
|
||||||
// navController.navigate("spell")
|
|
||||||
},
|
},
|
||||||
text = "Kerjakan Kuis",
|
text = "Kerjakan Kuis",
|
||||||
painter = painterResource(id = R.drawable.ic_next),
|
painter = painterResource(id = R.drawable.ic_next),
|
||||||
|
|
|
@ -7,6 +7,7 @@ import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import com.example.lexilearn.data.model.MaterialDataModel
|
import com.example.lexilearn.data.model.MaterialDataModel
|
||||||
import com.example.lexilearn.data.repository.MaterialRepository
|
import com.example.lexilearn.data.repository.MaterialRepository
|
||||||
|
import com.example.lexilearn.data.repository.QuizRepository
|
||||||
import com.example.lexilearn.domain.models.ModelSpell
|
import com.example.lexilearn.domain.models.ModelSpell
|
||||||
import com.example.lexilearn.utils.generateNumberList
|
import com.example.lexilearn.utils.generateNumberList
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
@ -20,6 +21,7 @@ class DetailMaterialViewModel(application: Application) : AndroidViewModel(appli
|
||||||
private val _isTTSInitialized = MutableLiveData(false)
|
private val _isTTSInitialized = MutableLiveData(false)
|
||||||
val isTTSInitialized: LiveData<Boolean> = _isTTSInitialized
|
val isTTSInitialized: LiveData<Boolean> = _isTTSInitialized
|
||||||
val alphabetList = generateNumberList()
|
val alphabetList = generateNumberList()
|
||||||
|
private val quizRepository = QuizRepository()
|
||||||
|
|
||||||
private val repository = MaterialRepository(application)
|
private val repository = MaterialRepository(application)
|
||||||
|
|
||||||
|
@ -46,6 +48,10 @@ class DetailMaterialViewModel(application: Application) : AndroidViewModel(appli
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun randomMaterialModel(): List<MaterialDataModel> {
|
||||||
|
return _materialList.value.shuffled()
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
tts = TextToSpeech(application, this)
|
tts = TextToSpeech(application, this)
|
||||||
}
|
}
|
||||||
|
|
|
@ -249,7 +249,7 @@ fun HomeScreen(navController: NavController) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ButtonHome(onClick = { },
|
ButtonHome(onClick = { navController.navigate("navMaterial/house") },
|
||||||
color = Color(0xffea2b72),
|
color = Color(0xffea2b72),
|
||||||
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
@ -304,7 +304,7 @@ fun HomeScreen(navController: NavController) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ButtonHome(onClick = { navController.navigate("read") },
|
ButtonHome(onClick = { navController.navigate("navMaterial/family") },
|
||||||
color = Color(0xffedb92f),
|
color = Color(0xffedb92f),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.constrainAs(newsRef) {
|
.constrainAs(newsRef) {
|
||||||
|
|
|
@ -17,6 +17,9 @@ import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
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.blur
|
import androidx.compose.ui.draw.blur
|
||||||
|
@ -44,6 +47,16 @@ fun NavMaterialScreen(navController: NavController, materialId: String) {
|
||||||
viewModel.fetchMaterial(materialId)
|
viewModel.fetchMaterial(materialId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val numberUnlock by navController.currentBackStackEntry
|
||||||
|
?.savedStateHandle
|
||||||
|
?.getLiveData<Int>("numberUnlock")
|
||||||
|
?.observeAsState(initial = 0) ?: remember { mutableIntStateOf(0) }
|
||||||
|
|
||||||
|
LaunchedEffect(numberUnlock) {
|
||||||
|
println("printUpdateUnlock-nav $numberUnlock")
|
||||||
|
viewModel.updateUnlockValue(materialId, numberUnlock)
|
||||||
|
}
|
||||||
|
|
||||||
val materialList by viewModel.materialList.collectAsState()
|
val materialList by viewModel.materialList.collectAsState()
|
||||||
val textTitle by viewModel.textTitle.observeAsState("")
|
val textTitle by viewModel.textTitle.observeAsState("")
|
||||||
val sizeUnlock by viewModel.sizeUnlock.observeAsState()
|
val sizeUnlock by viewModel.sizeUnlock.observeAsState()
|
||||||
|
@ -89,6 +102,9 @@ fun NavMaterialScreen(navController: NavController, materialId: String) {
|
||||||
"materialList",
|
"materialList",
|
||||||
chunk
|
chunk
|
||||||
)
|
)
|
||||||
|
navController.currentBackStackEntry?.savedStateHandle?.set(
|
||||||
|
"indexValue", index
|
||||||
|
)
|
||||||
navController.navigate("detailMaterial")
|
navController.navigate("detailMaterial")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -73,6 +73,19 @@ class NavMaterialViewModel(application: Application) : AndroidViewModel(applicat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateUnlockValue(materialId: String, value: Int) {
|
||||||
|
if(value >= (_sizeUnlock.value ?: 0) && _materialList.value.size > value){
|
||||||
|
viewModelScope.launch {
|
||||||
|
repository.updateUnlockData(materialId, value){
|
||||||
|
println("numberUnlock update unlock value success $it")
|
||||||
|
fetchMaterial(materialId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
println("numberUnlock-else $value, ${_sizeUnlock.value}, ${_materialList.value.size}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
tts?.stop()
|
tts?.stop()
|
||||||
tts?.shutdown()
|
tts?.shutdown()
|
||||||
|
|
|
@ -42,6 +42,7 @@ import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.SnackbarHost
|
import androidx.compose.material3.SnackbarHost
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.runtime.key
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
import androidx.compose.runtime.mutableStateMapOf
|
import androidx.compose.runtime.mutableStateMapOf
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
@ -50,6 +51,7 @@ 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
|
||||||
import androidx.compose.ui.unit.IntOffset
|
import androidx.compose.ui.unit.IntOffset
|
||||||
|
import androidx.compose.ui.zIndex
|
||||||
import androidx.constraintlayout.compose.ConstraintLayout
|
import androidx.constraintlayout.compose.ConstraintLayout
|
||||||
import com.example.lexilearn.R
|
import com.example.lexilearn.R
|
||||||
import com.example.lexilearn.data.model.QuestionType
|
import com.example.lexilearn.data.model.QuestionType
|
||||||
|
@ -67,9 +69,12 @@ import kotlin.math.roundToInt
|
||||||
@Composable
|
@Composable
|
||||||
fun QuizScreen(
|
fun QuizScreen(
|
||||||
navController: NavController,
|
navController: NavController,
|
||||||
material: MaterialDataModel,
|
materials: List<MaterialDataModel>,
|
||||||
|
typeQuiz: String,
|
||||||
|
indexValue: Int,
|
||||||
quizViewModel: QuizViewModel = viewModel()
|
quizViewModel: QuizViewModel = viewModel()
|
||||||
) {
|
) {
|
||||||
|
println("testco tipe: ${typeQuiz}, index = ${indexValue}")
|
||||||
val question by quizViewModel.currentQuestion.collectAsState()
|
val question by quizViewModel.currentQuestion.collectAsState()
|
||||||
val isButtonVisible by quizViewModel.isButtonVisible
|
val isButtonVisible by quizViewModel.isButtonVisible
|
||||||
val isAnswerCorrect by quizViewModel.isAnswerCorrect.collectAsState()
|
val isAnswerCorrect by quizViewModel.isAnswerCorrect.collectAsState()
|
||||||
|
@ -77,16 +82,8 @@ fun QuizScreen(
|
||||||
val snackbarMessage by quizViewModel.snackbarMessage.collectAsState()
|
val snackbarMessage by quizViewModel.snackbarMessage.collectAsState()
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
|
|
||||||
|
val indexQuiz by quizViewModel.indexQuiz.collectAsState()
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
|
||||||
quizViewModel.loadRandomQuestion(material)
|
|
||||||
}
|
|
||||||
LaunchedEffect(snackbarMessage) {
|
|
||||||
snackbarMessage?.let { message ->
|
|
||||||
snackbarHostState.showSnackbar(message)
|
|
||||||
quizViewModel.onSnackbarShown()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var rectColumnAnswer by remember { mutableStateOf(Rect.Zero) }
|
var rectColumnAnswer by remember { mutableStateOf(Rect.Zero) }
|
||||||
|
|
||||||
|
@ -128,10 +125,50 @@ fun QuizScreen(
|
||||||
mutableStateMapOf<Int, Rect>()
|
mutableStateMapOf<Int, Rect>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun clearOffsets() {
|
||||||
|
boxRectAnswer.clear()
|
||||||
|
boxRectDragable.clear()
|
||||||
|
cardSize.clear()
|
||||||
|
quizXOffset.clear()
|
||||||
|
quizYOffset.clear()
|
||||||
|
boxRectQuiz.clear()
|
||||||
|
answerXOffset.clear()
|
||||||
|
answerYOffset.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
quizViewModel.initMaterialData(materials)
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(indexQuiz) {
|
||||||
|
println("indexQuizValue = $indexQuiz")
|
||||||
|
if (indexQuiz < materials.size) {
|
||||||
|
clearOffsets()
|
||||||
|
quizViewModel.randomQuestion()
|
||||||
|
} else {
|
||||||
|
navController.getBackStackEntry("navMaterial/$typeQuiz")
|
||||||
|
.savedStateHandle
|
||||||
|
.set("numberUnlock", indexValue + 1)
|
||||||
|
println("printUpdateUnlock-quiz $indexValue")
|
||||||
|
// Kemudian kembali ke halaman sebelumnya
|
||||||
|
navController.popBackStack()
|
||||||
|
navController.popBackStack()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LaunchedEffect(snackbarMessage) {
|
||||||
|
snackbarMessage?.let { message ->
|
||||||
|
snackbarHostState.showSnackbar(message)
|
||||||
|
quizViewModel.onSnackbarShown()
|
||||||
|
}
|
||||||
|
}
|
||||||
Scaffold(
|
Scaffold(
|
||||||
snackbarHost = { SnackbarHost(hostState = snackbarHostState) }
|
snackbarHost = { SnackbarHost(hostState = snackbarHostState) }
|
||||||
){innerPadding->
|
) { innerPadding ->
|
||||||
Surface(modifier = Modifier.fillMaxSize().padding(innerPadding)) {
|
Surface(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(innerPadding)
|
||||||
|
) {
|
||||||
GradientQuiz(
|
GradientQuiz(
|
||||||
navController = navController,
|
navController = navController,
|
||||||
headerText = stringResource(id = R.string.spelltitle),
|
headerText = stringResource(id = R.string.spelltitle),
|
||||||
|
@ -205,6 +242,7 @@ fun QuizScreen(
|
||||||
|
|
||||||
) {
|
) {
|
||||||
dataQuiz.forEach { dt ->
|
dataQuiz.forEach { dt ->
|
||||||
|
key(dt.id) {
|
||||||
val id = dt.id
|
val id = dt.id
|
||||||
if (!boxRectDragable.containsKey(id))
|
if (!boxRectDragable.containsKey(id))
|
||||||
boxRectDragable[id] = Rect.Zero
|
boxRectDragable[id] = Rect.Zero
|
||||||
|
@ -217,11 +255,13 @@ fun QuizScreen(
|
||||||
|
|
||||||
CardQuiz(
|
CardQuiz(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
.zIndex(zIndex = 1f)
|
||||||
.padding(vertical = 10.dp)
|
.padding(vertical = 10.dp)
|
||||||
.size(minSize)
|
.size(minSize)
|
||||||
.onGloballyPositioned { coordinates ->
|
.onGloballyPositioned { coordinates ->
|
||||||
if (dt.type)
|
if (dt.type)
|
||||||
boxRectQuiz[id] = coordinates.boundsInWindow()
|
boxRectQuiz[id] =
|
||||||
|
coordinates.boundsInWindow()
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
if (dt.type) {
|
if (dt.type) {
|
||||||
|
@ -237,8 +277,10 @@ fun QuizScreen(
|
||||||
item = dt.data,
|
item = dt.data,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.offset {
|
.offset {
|
||||||
val xOffset = quizXOffset[id] ?: 0f
|
val xOffset =
|
||||||
val yOffset = quizYOffset[id] ?: 0f
|
quizXOffset[id] ?: 0f
|
||||||
|
val yOffset =
|
||||||
|
quizYOffset[id] ?: 0f
|
||||||
IntOffset(
|
IntOffset(
|
||||||
xOffset.roundToInt(),
|
xOffset.roundToInt(),
|
||||||
yOffset.roundToInt()
|
yOffset.roundToInt()
|
||||||
|
@ -277,13 +319,17 @@ fun QuizScreen(
|
||||||
dt
|
dt
|
||||||
)
|
)
|
||||||
dt.apply {
|
dt.apply {
|
||||||
hasContent = false
|
hasContent =
|
||||||
showCard = false
|
false
|
||||||
|
showCard =
|
||||||
|
false
|
||||||
data = "?"
|
data = "?"
|
||||||
}
|
}
|
||||||
checkNull = true
|
checkNull = true
|
||||||
quizXOffset[id] = 0f
|
quizXOffset[id] =
|
||||||
quizYOffset[id] = 0f
|
0f
|
||||||
|
quizYOffset[id] =
|
||||||
|
0f
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,14 +340,19 @@ fun QuizScreen(
|
||||||
val emDt = dt.emp
|
val emDt = dt.emp
|
||||||
if (emDt != null) {
|
if (emDt != null) {
|
||||||
dt.apply {
|
dt.apply {
|
||||||
hasContent = false
|
hasContent =
|
||||||
showCard = false
|
false
|
||||||
|
showCard =
|
||||||
|
false
|
||||||
data = "?"
|
data = "?"
|
||||||
}
|
}
|
||||||
checkNull = true
|
checkNull = true
|
||||||
cardSize[emDt] = maxSize
|
cardSize[emDt] =
|
||||||
quizXOffset[id] = 0f
|
maxSize
|
||||||
quizYOffset[id] = 0f
|
quizXOffset[id] =
|
||||||
|
0f
|
||||||
|
quizYOffset[id] =
|
||||||
|
0f
|
||||||
dt.data = "?"
|
dt.data = "?"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -328,6 +379,7 @@ fun QuizScreen(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -353,6 +405,7 @@ fun QuizScreen(
|
||||||
horizontalArrangement = Arrangement.Center
|
horizontalArrangement = Arrangement.Center
|
||||||
) {
|
) {
|
||||||
rowItems.forEach { item ->
|
rowItems.forEach { item ->
|
||||||
|
key(item.id) {
|
||||||
val id = item.id
|
val id = item.id
|
||||||
if (!cardSize.containsKey(id))
|
if (!cardSize.containsKey(id))
|
||||||
cardSize[id] = maxSize
|
cardSize[id] = maxSize
|
||||||
|
@ -374,7 +427,8 @@ fun QuizScreen(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.onGloballyPositioned { coordinates ->
|
.onGloballyPositioned { coordinates ->
|
||||||
boxRectAnswer[id] = coordinates.boundsInWindow()
|
boxRectAnswer[id] =
|
||||||
|
coordinates.boundsInWindow()
|
||||||
}
|
}
|
||||||
.pointerInput(Unit) {
|
.pointerInput(Unit) {
|
||||||
detectDragGestures(
|
detectDragGestures(
|
||||||
|
@ -427,6 +481,7 @@ fun QuizScreen(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,9 @@ class QuizViewModel(application: Application) : AndroidViewModel(application),
|
||||||
TextToSpeech.OnInitListener {
|
TextToSpeech.OnInitListener {
|
||||||
private val quizRepository = QuizRepository()
|
private val quizRepository = QuizRepository()
|
||||||
|
|
||||||
|
|
||||||
|
private var materialList: List<MaterialDataModel> = emptyList()
|
||||||
|
|
||||||
private val _currentQuestion = MutableStateFlow<QuizQuestion?>(null)
|
private val _currentQuestion = MutableStateFlow<QuizQuestion?>(null)
|
||||||
val currentQuestion: StateFlow<QuizQuestion?> = _currentQuestion
|
val currentQuestion: StateFlow<QuizQuestion?> = _currentQuestion
|
||||||
|
|
||||||
|
@ -33,6 +36,14 @@ class QuizViewModel(application: Application) : AndroidViewModel(application),
|
||||||
private val _isAnswerCorrect = MutableStateFlow<Boolean?>(null)
|
private val _isAnswerCorrect = MutableStateFlow<Boolean?>(null)
|
||||||
val isAnswerCorrect: StateFlow<Boolean?> = _isAnswerCorrect
|
val isAnswerCorrect: StateFlow<Boolean?> = _isAnswerCorrect
|
||||||
|
|
||||||
|
private val _indexQuiz = MutableStateFlow(0)
|
||||||
|
val indexQuiz: StateFlow<Int> = _indexQuiz
|
||||||
|
|
||||||
|
// Update indexQuiz saat jawaban benar
|
||||||
|
fun incrementIndexQuiz() {
|
||||||
|
_indexQuiz.value += 1
|
||||||
|
}
|
||||||
|
|
||||||
fun loadNewQuestion(material: MaterialDataModel, questionMode: Int, answerMode: Int) {
|
fun loadNewQuestion(material: MaterialDataModel, questionMode: Int, answerMode: Int) {
|
||||||
_currentQuestion.value = quizRepository.generateQuestion(material, questionMode, answerMode)
|
_currentQuestion.value = quizRepository.generateQuestion(material, questionMode, answerMode)
|
||||||
}
|
}
|
||||||
|
@ -63,28 +74,49 @@ class QuizViewModel(application: Application) : AndroidViewModel(application),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun loadRandomQuestion(material: MaterialDataModel) {
|
fun initMaterialData(material: List<MaterialDataModel>) {
|
||||||
_currentQuestion.value = quizRepository.generateQuestion(material, 2, 2)
|
materialList = material;
|
||||||
|
}
|
||||||
|
|
||||||
val dataQuest =
|
// fun randomQuestion() {
|
||||||
_currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char ->
|
// _currentQuestion.value = quizRepository.generateQuestion(materialList[_indexQuiz.value], 2, 2)
|
||||||
ModelSpell(index + 1, true, "?", showCard = false)
|
// val dataQuest =
|
||||||
|
// _currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char ->
|
||||||
|
// ModelSpell(index + 1, true, data = "coba $char", showCard = false)
|
||||||
|
// } ?: emptyList()
|
||||||
|
// _questionShuffled.value = dataQuest
|
||||||
|
//
|
||||||
|
// val listAnswer =
|
||||||
|
// _currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char ->
|
||||||
|
// ModelAnswerRead(index + 1, char.toString())
|
||||||
|
// } ?: emptyList()
|
||||||
|
// val shuflledAnswer = listAnswer.shuffled()
|
||||||
|
// _shuffledAnswerLetters.value = shuflledAnswer
|
||||||
|
// println("testlistanswer ${_shuffledAnswerLetters.value}")
|
||||||
|
// }
|
||||||
|
// Di dalam fungsi randomQuestion() pada QuizViewModel
|
||||||
|
fun randomQuestion() {
|
||||||
|
_currentQuestion.value = quizRepository.generateQuestion(materialList[_indexQuiz.value], 2, 2)
|
||||||
|
|
||||||
|
// Generate unique IDs berdasarkan indexQuiz dan indeks karakter
|
||||||
|
val dataQuest = _currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char ->
|
||||||
|
ModelSpell(
|
||||||
|
id = (_indexQuiz.value * 100) + index + 1, // ID unik per pertanyaan
|
||||||
|
type = true,
|
||||||
|
data = "?",
|
||||||
|
showCard = false
|
||||||
|
)
|
||||||
} ?: emptyList()
|
} ?: emptyList()
|
||||||
_questionShuffled.value = dataQuest
|
_questionShuffled.value = dataQuest
|
||||||
|
|
||||||
val listAnswer =
|
val listAnswer = _currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char ->
|
||||||
_currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char ->
|
ModelAnswerRead(
|
||||||
ModelAnswerRead(index + 1, char.toString())
|
id = (_indexQuiz.value * 100) + index + 1, // ID unik per pertanyaan
|
||||||
|
data = char.toString()
|
||||||
|
)
|
||||||
} ?: emptyList()
|
} ?: emptyList()
|
||||||
val shuflledAnswer = listAnswer.shuffled()
|
_shuffledAnswerLetters.value = listAnswer.shuffled()
|
||||||
_shuffledAnswerLetters.value = shuflledAnswer
|
}
|
||||||
|
|
||||||
// Menambahkan delay 1 detik sebelum memanggil observeData()
|
|
||||||
// viewModelScope.launch {
|
|
||||||
// delay(1000L) // delay 1 detik
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun submitAnswer(answer: String) {
|
fun submitAnswer(answer: String) {
|
||||||
|
@ -139,6 +171,7 @@ class QuizViewModel(application: Application) : AndroidViewModel(application),
|
||||||
val checkData = checkAnswer(answerString);
|
val checkData = checkAnswer(answerString);
|
||||||
if (checkData) {
|
if (checkData) {
|
||||||
triggerSnackbar("Jawaban Benar")
|
triggerSnackbar("Jawaban Benar")
|
||||||
|
incrementIndexQuiz()
|
||||||
} else {
|
} else {
|
||||||
triggerSnackbar("Jawaban Salah")
|
triggerSnackbar("Jawaban Salah")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue