Update New Feature
This commit is contained in:
parent
0cdd33997d
commit
3824e79c2a
|
@ -1,6 +1,8 @@
|
|||
package com.example.lexilearn
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.compose.runtime.Composable
|
||||
|
@ -8,6 +10,8 @@ import androidx.navigation.compose.NavHost
|
|||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.example.lexilearn.data.model.MaterialDataModel
|
||||
import com.example.lexilearn.data.model.UserModel
|
||||
import com.example.lexilearn.data.repository.MaterialRepository
|
||||
import com.example.lexilearn.ui.views.pDetailMaterial.DetailMaterialScreen
|
||||
import com.example.lexilearn.ui.views.pHome.HomeScreen
|
||||
import com.example.lexilearn.ui.views.pLearAlphabet.LearnAlphabetScreen
|
||||
|
@ -21,13 +25,49 @@ import com.example.lexilearn.ui.views.pRegister.RegisterScreen
|
|||
import com.example.lexilearn.ui.views.pResultScreening.ResultScreeningScreen
|
||||
import com.example.lexilearn.ui.views.pScreening.ScreeningScreen
|
||||
import com.example.lexilearn.ui.views.pSplashcreen.SplashScreen
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val repository = MaterialRepository(this)
|
||||
|
||||
// 🔥 Default email & password
|
||||
val email = "example@gmail.com"
|
||||
val password = "example123"
|
||||
|
||||
// 🔥 Coba login
|
||||
repository.loginUser(email, password) { success, userId ->
|
||||
if (success) {
|
||||
Toast.makeText(this, "Login Berhasil! ID: $userId", Toast.LENGTH_SHORT).show()
|
||||
Log.d("MainActivity", "Login Berhasil! User ID: $userId")
|
||||
} else {
|
||||
Log.e("MainActivity", "User tidak ditemukan, membuat akun baru...")
|
||||
|
||||
// 🔥 Jika tidak ditemukan, buat user baru
|
||||
val newUser = UserModel(
|
||||
email = email,
|
||||
name = "Example User",
|
||||
password = password,
|
||||
unlock_data = UserModel.UnlockData()
|
||||
)
|
||||
|
||||
repository.createUser(newUser) { success, newUserId ->
|
||||
if (success) {
|
||||
Toast.makeText(this, "User Baru Dibuat! Login Sekarang...", Toast.LENGTH_SHORT).show()
|
||||
repository.loginUser(email, password) { loginSuccess, loggedInUserId ->
|
||||
if (loginSuccess) {
|
||||
Log.d("MainActivity", "Login Berhasil setelah buat akun! User ID: $loggedInUserId")
|
||||
} else {
|
||||
Log.e("MainActivity", "Login Gagal setelah membuat akun!")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.e("MainActivity", "Gagal membuat user baru!")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
setContent {
|
||||
MyApp()
|
||||
}
|
||||
|
|
|
@ -3,23 +3,42 @@ package com.example.lexilearn.data.local
|
|||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import com.example.lexilearn.data.model.MaterialDataModel
|
||||
import com.example.lexilearn.data.model.UserModel
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
|
||||
class SharedPrefHelper(context: Context) {
|
||||
|
||||
private val sharedPreferences: SharedPreferences =
|
||||
context.getSharedPreferences("MaterialDataPrefs", Context.MODE_PRIVATE)
|
||||
context.getSharedPreferences("UserPrefs", Context.MODE_PRIVATE)
|
||||
|
||||
fun saveMaterialList(materialList: List<MaterialDataModel>) {
|
||||
// 🔥 Simpan User ID setelah login
|
||||
fun saveUserId(userId: String) {
|
||||
val editor = sharedPreferences.edit()
|
||||
val json = Gson().toJson(materialList)
|
||||
editor.putString("material_list", json)
|
||||
editor.putString("user_id", userId)
|
||||
editor.apply()
|
||||
}
|
||||
|
||||
fun getMaterialList(): List<MaterialDataModel>? {
|
||||
val json = sharedPreferences.getString("material_list", null)
|
||||
// 🔥 Ambil User ID yang tersimpan
|
||||
fun getUserId(): String? {
|
||||
return sharedPreferences.getString("user_id", null)
|
||||
}
|
||||
|
||||
// 🔥 Hapus data user saat logout
|
||||
fun clearUserData() {
|
||||
sharedPreferences.edit().clear().apply()
|
||||
}
|
||||
|
||||
// 🔥 Fungsi SharedPreferences untuk menyimpan daftar material (kode lama, tetap dipertahankan)
|
||||
fun saveMaterialList(filterMaterial: String, materialList: List<MaterialDataModel>) {
|
||||
val editor = sharedPreferences.edit()
|
||||
val json = Gson().toJson(materialList)
|
||||
editor.putString("material_list_$filterMaterial", json)
|
||||
editor.apply()
|
||||
}
|
||||
|
||||
fun getMaterialList(filterMaterial: String): List<MaterialDataModel>? {
|
||||
val json = sharedPreferences.getString("material_list_$filterMaterial", null)
|
||||
return if (json != null) {
|
||||
val type = object : TypeToken<List<MaterialDataModel>>() {}.type
|
||||
Gson().fromJson(json, type)
|
||||
|
@ -28,7 +47,27 @@ class SharedPrefHelper(context: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
fun clearMaterialList() {
|
||||
sharedPreferences.edit().remove("material_list").apply()
|
||||
fun clearMaterialList(filterMaterial: String) {
|
||||
sharedPreferences.edit().remove("material_list_$filterMaterial").apply()
|
||||
}
|
||||
|
||||
fun clearAllMaterialData() {
|
||||
sharedPreferences.edit().clear().apply()
|
||||
}
|
||||
|
||||
fun getUserData(): UserModel? {
|
||||
val json = sharedPreferences.getString("user_data", null)
|
||||
return if (json != null) {
|
||||
Gson().fromJson(json, UserModel::class.java)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun saveUserData(user: UserModel) {
|
||||
val editor = sharedPreferences.edit()
|
||||
val json = Gson().toJson(user)
|
||||
editor.putString("user_data", json)
|
||||
editor.apply()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package com.example.lexilearn.data.model
|
||||
|
||||
data class UserModel(
|
||||
var email: String = "",
|
||||
var name: String = "",
|
||||
var password: String = "",
|
||||
var unlock_data: UnlockData = UnlockData() // 🔥 Perbaiki cara mendeklarasikan UnlockData
|
||||
) {
|
||||
data class UnlockData(
|
||||
var animal: Int = 0,
|
||||
var family: Int = 0,
|
||||
var house: Int = 0,
|
||||
var limb: Int = 0
|
||||
)
|
||||
}
|
|
@ -5,17 +5,19 @@ import android.content.Context
|
|||
import android.util.Log
|
||||
import com.example.lexilearn.data.model.MaterialDataModel
|
||||
import com.example.lexilearn.data.local.SharedPrefHelper
|
||||
import com.example.lexilearn.data.model.UserModel
|
||||
import com.google.firebase.database.*
|
||||
import com.google.firebase.database.DatabaseReference
|
||||
import com.google.firebase.database.FirebaseDatabase
|
||||
|
||||
class FirebaseHelper(private val context: Context) {
|
||||
private val databaseReference: DatabaseReference =
|
||||
FirebaseDatabase.getInstance().getReference("data/animal")
|
||||
|
||||
private val sharedPrefHelper = SharedPrefHelper(context)
|
||||
|
||||
fun fetchMaterials(callback: (List<MaterialDataModel>) -> Unit) {
|
||||
// 🔥 Fungsi untuk mengambil data berdasarkan filterMaterial (kode lama, tetap dipertahankan)
|
||||
fun fetchMaterials(filterMaterial: String, callback: (List<MaterialDataModel>) -> Unit) {
|
||||
val databaseReference: DatabaseReference =
|
||||
FirebaseDatabase.getInstance().getReference("data/$filterMaterial")
|
||||
|
||||
databaseReference.addListenerForSingleValueEvent(object : ValueEventListener {
|
||||
override fun onDataChange(snapshot: DataSnapshot) {
|
||||
val materialList = mutableListOf<MaterialDataModel>()
|
||||
|
@ -24,8 +26,7 @@ class FirebaseHelper(private val context: Context) {
|
|||
material?.let { materialList.add(it) }
|
||||
}
|
||||
|
||||
// Simpan ke SharedPreferences agar bisa diakses tanpa internet
|
||||
sharedPrefHelper.saveMaterialList(materialList)
|
||||
sharedPrefHelper.saveMaterialList(filterMaterial, materialList)
|
||||
callback(materialList)
|
||||
}
|
||||
|
||||
|
@ -34,4 +35,53 @@ class FirebaseHelper(private val context: Context) {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
// ✅ 🔥 Fungsi Login - Mencari user berdasarkan email dan password
|
||||
fun loginUser(email: String, password: String, callback: (Boolean, String?) -> Unit) {
|
||||
val databaseReference: DatabaseReference = FirebaseDatabase.getInstance().getReference("users")
|
||||
|
||||
databaseReference.addListenerForSingleValueEvent(object : ValueEventListener {
|
||||
override fun onDataChange(snapshot: DataSnapshot) {
|
||||
for (userSnapshot in snapshot.children) {
|
||||
val user = userSnapshot.getValue(UserModel::class.java)
|
||||
if (user != null && user.email == email && user.password == password) {
|
||||
val userId = userSnapshot.key // Ambil ID pengguna
|
||||
sharedPrefHelper.saveUserId(userId!!) // Simpan ID ke SharedPreferences
|
||||
callback(true, userId)
|
||||
return
|
||||
}
|
||||
}
|
||||
callback(false, null) // Jika tidak ditemukan
|
||||
}
|
||||
|
||||
override fun onCancelled(error: DatabaseError) {
|
||||
Log.e("FirebaseHelper", "Error: ${error.message}")
|
||||
callback(false, null)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// ✅ 🔥 Fungsi Fetch User Data Berdasarkan ID (Dapatkan data user setelah login)
|
||||
fun fetchUserData(callback: (UserModel?) -> Unit) {
|
||||
val userId = sharedPrefHelper.getUserId()
|
||||
|
||||
if (userId == null) {
|
||||
callback(null)
|
||||
return
|
||||
}
|
||||
|
||||
val databaseReference: DatabaseReference = FirebaseDatabase.getInstance().getReference("users/$userId")
|
||||
|
||||
databaseReference.addListenerForSingleValueEvent(object : ValueEventListener {
|
||||
override fun onDataChange(snapshot: DataSnapshot) {
|
||||
val user = snapshot.getValue(UserModel::class.java)
|
||||
callback(user)
|
||||
}
|
||||
|
||||
override fun onCancelled(error: DatabaseError) {
|
||||
Log.e("FirebaseHelper", "Error: ${error.message}")
|
||||
callback(null)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,20 +4,129 @@ import android.content.Context
|
|||
import com.example.lexilearn.data.local.SharedPrefHelper
|
||||
import com.example.lexilearn.data.remote.FirebaseHelper
|
||||
import com.example.lexilearn.data.model.MaterialDataModel
|
||||
|
||||
import com.example.lexilearn.data.model.UserModel
|
||||
import com.google.firebase.database.FirebaseDatabase
|
||||
|
||||
class MaterialRepository(private val context: Context) {
|
||||
private val sharedPrefHelper = SharedPrefHelper(context)
|
||||
private val firebaseHelper = FirebaseHelper(context)
|
||||
|
||||
fun getMaterialData(callback: (List<MaterialDataModel>) -> Unit) {
|
||||
val cachedData = sharedPrefHelper.getMaterialList()
|
||||
fun getMaterialData(filterMaterial: String, callback: (List<MaterialDataModel>) -> Unit) {
|
||||
val cachedData =
|
||||
sharedPrefHelper.getMaterialList(filterMaterial) // Ambil data dengan filter
|
||||
if (cachedData != null) {
|
||||
callback(cachedData)
|
||||
} else {
|
||||
firebaseHelper.fetchMaterials { materials ->
|
||||
firebaseHelper.fetchMaterials(filterMaterial) { materials ->
|
||||
sharedPrefHelper.saveMaterialList(
|
||||
filterMaterial,
|
||||
materials
|
||||
)
|
||||
callback(materials)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createUser(user: UserModel, callback: (Boolean, String?) -> Unit) {
|
||||
val databaseReference = FirebaseDatabase.getInstance().getReference("users")
|
||||
|
||||
// Buat user baru dengan ID unik
|
||||
val userId = databaseReference.push().key
|
||||
|
||||
if (userId != null) {
|
||||
databaseReference.child(userId).setValue(user).addOnCompleteListener { task ->
|
||||
if (task.isSuccessful) {
|
||||
sharedPrefHelper.saveUserId(userId) // Simpan user ID
|
||||
callback(true, userId)
|
||||
} else {
|
||||
callback(false, null)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
callback(false, null)
|
||||
}
|
||||
}
|
||||
|
||||
fun loginUser(email: String, password: String, callback: (Boolean, String?) -> Unit) {
|
||||
firebaseHelper.loginUser(email, password) { success, userId ->
|
||||
if (success && userId != null) {
|
||||
sharedPrefHelper.saveUserId(userId) // Simpan ID user
|
||||
callback(true, userId)
|
||||
} else {
|
||||
callback(false, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getUserData(callback: (UserModel?) -> Unit) {
|
||||
firebaseHelper.fetchUserData { user ->
|
||||
callback(user)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateUnlockData(idUnlock: String, value: Int, callback: (Boolean) -> Unit) {
|
||||
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
|
||||
userRef.get().addOnSuccessListener { snapshot ->
|
||||
val currentValue = snapshot.getValue(Int::class.java) ?: 0
|
||||
|
||||
// 🔥 Hanya update jika nilai baru lebih besar
|
||||
if (value > currentValue) {
|
||||
userRef.setValue(value).addOnCompleteListener { task ->
|
||||
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
|
||||
}
|
||||
}
|
||||
sharedPrefHelper.saveUserData(updatedUser!!)
|
||||
callback(true)
|
||||
} else {
|
||||
callback(false)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
callback(false) // 🔥 Jika nilai baru <= nilai lama, tidak update
|
||||
}
|
||||
}.addOnFailureListener {
|
||||
callback(false)
|
||||
}
|
||||
}
|
||||
|
||||
fun getUnlockValue(idUnlock: String, callback: (Int?) -> Unit) {
|
||||
val userId = sharedPrefHelper.getUserId()
|
||||
|
||||
if (userId == null) {
|
||||
callback(null)
|
||||
return
|
||||
}
|
||||
|
||||
val userRef = FirebaseDatabase.getInstance().getReference("users/$userId/unlock_data/$idUnlock")
|
||||
|
||||
// 🔥 Ambil nilai dari Firebase
|
||||
userRef.get().addOnSuccessListener { snapshot ->
|
||||
val currentValue = snapshot.getValue(Int::class.java) ?: 0
|
||||
callback(currentValue)
|
||||
}.addOnFailureListener {
|
||||
callback(null) // 🔥 Gagal mengambil data
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun logoutUser() {
|
||||
sharedPrefHelper.clearUserData()
|
||||
}
|
||||
}
|
|
@ -49,13 +49,14 @@ fun DetailMaterialScreen(navController: NavController, materialListData: List<Ma
|
|||
}
|
||||
|
||||
val materialList by viewModel.materialList.collectAsState()
|
||||
val textTitle by viewModel.textTitle.observeAsState("")
|
||||
|
||||
val isTTSInitialized = viewModel.isTTSInitialized.observeAsState(false)
|
||||
|
||||
Surface(modifier = Modifier.fillMaxSize()) {
|
||||
GradientQuiz(
|
||||
navController = navController,
|
||||
headerText = "Detail Hewan",
|
||||
headerText = "Belajar materi $textTitle",
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
Column(
|
||||
|
@ -72,30 +73,11 @@ fun DetailMaterialScreen(navController: NavController, materialListData: List<Ma
|
|||
items(materialList) { dataMat ->
|
||||
ConstraintLayout(modifier = Modifier.fillMaxWidth()) {
|
||||
val (refButton) = createRefs()
|
||||
IconButton(
|
||||
onClick = {
|
||||
viewModel.speakLetter(dataMat.enName)
|
||||
},
|
||||
modifier = Modifier
|
||||
.size(80.dp).constrainAs(refButton) {
|
||||
top.linkTo(parent.top)
|
||||
end.linkTo(parent.end)
|
||||
} // 🔥 Ukuran tombol bisa disesuaikan
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.VolumeUp, // 🔥 Ikon Speaker dari Material Icons
|
||||
contentDescription = "Speaker Icon",
|
||||
tint = Color.Black // 🔥 Warna ikon
|
||||
)
|
||||
}
|
||||
Column {
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.border(2.dp, color = ctextBlack, RoundedCornerShape(8.dp))
|
||||
.clickable {
|
||||
viewModel.speakLetter(dataMat.enName)
|
||||
},
|
||||
.border(2.dp, color = ctextBlack, RoundedCornerShape(8.dp)),
|
||||
shape = RoundedCornerShape(8.dp),
|
||||
colors = CardDefaults.cardColors(containerColor = Color.White)
|
||||
) {
|
||||
|
@ -151,6 +133,23 @@ fun DetailMaterialScreen(navController: NavController, materialListData: List<Ma
|
|||
}
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
}
|
||||
IconButton(
|
||||
onClick = {
|
||||
viewModel.speakLetter(dataMat.enName)
|
||||
},
|
||||
modifier = Modifier
|
||||
.size(80.dp)
|
||||
.constrainAs(refButton) {
|
||||
top.linkTo(parent.top)
|
||||
end.linkTo(parent.end)
|
||||
} // 🔥 Ukuran tombol bisa disesuaikan
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.VolumeUp, // 🔥 Ikon Speaker dari Material Icons
|
||||
contentDescription = "Speaker Icon",
|
||||
tint = Color.Black // 🔥 Warna ikon
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,13 +5,11 @@ import android.speech.tts.TextToSpeech
|
|||
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.repository.MaterialRepository
|
||||
import com.example.lexilearn.utils.generateNumberList
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.*
|
||||
|
||||
class DetailMaterialViewModel(application: Application) : AndroidViewModel(application),
|
||||
|
@ -27,8 +25,22 @@ class DetailMaterialViewModel(application: Application) : AndroidViewModel(appli
|
|||
private val _materialList = MutableStateFlow<List<MaterialDataModel>>(emptyList())
|
||||
val materialList: StateFlow<List<MaterialDataModel>> = _materialList
|
||||
|
||||
private val _textTitle = MutableLiveData("Hello, Jetpack Compose!")
|
||||
val textTitle: LiveData<String> = _textTitle
|
||||
|
||||
fun fetchMaterial(materialListData: List<MaterialDataModel>) {
|
||||
_materialList.value = materialListData
|
||||
if (materialListData.isNotEmpty()) {
|
||||
if (materialListData[0].category == "animal") {
|
||||
_textTitle.value = "hewan"
|
||||
} else if (materialListData[0].category == "limb") {
|
||||
_textTitle.value = "anggota tubuh"
|
||||
}else if (materialListData[0].category == "house") {
|
||||
_textTitle.value = "bagian rumah"
|
||||
}else if (materialListData[0].category == "family") {
|
||||
_textTitle.value = "anggota keluarga"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
|
|
|
@ -222,7 +222,7 @@ fun HomeScreen(navController: NavController) {
|
|||
.fillMaxWidth()
|
||||
) {
|
||||
val (quizRef, alphabetRef, screeningRef, newsRef) = createRefs()
|
||||
ButtonHome(onClick = { navController.navigate("read") },
|
||||
ButtonHome(onClick = { navController.navigate("navMaterial/limb") },
|
||||
color = Color(0xff47bff0),
|
||||
modifier = Modifier
|
||||
.constrainAs(quizRef) {
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
package com.example.lexilearn.ui.views.pNavMaterial
|
||||
|
||||
import android.graphics.Shader
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Lock
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
|
@ -17,6 +22,9 @@ import androidx.compose.runtime.livedata.observeAsState
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.RenderEffect
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
@ -31,7 +39,7 @@ import com.example.lexilearn.ui.theme.cAccent
|
|||
import com.example.lexilearn.ui.theme.cGray
|
||||
import com.example.lexilearn.ui.theme.ctextGray
|
||||
import com.example.lexilearn.ui.theme.cwhite
|
||||
import com.google.gson.Gson
|
||||
|
||||
|
||||
@Composable
|
||||
fun NavMaterialScreen(navController: NavController, materialId: String) {
|
||||
|
@ -41,13 +49,15 @@ fun NavMaterialScreen(navController: NavController, materialId: String) {
|
|||
}
|
||||
|
||||
val materialList by viewModel.materialList.collectAsState()
|
||||
val textTitle by viewModel.textTitle.observeAsState("")
|
||||
val sizeUnlock by viewModel.sizeUnlock.observeAsState()
|
||||
|
||||
val isTTSInitialized = viewModel.isTTSInitialized.observeAsState(false)
|
||||
|
||||
Surface(modifier = Modifier.fillMaxSize()) {
|
||||
GradientQuiz(
|
||||
navController = navController,
|
||||
headerText = "Belajar Hewan",
|
||||
headerText = "Belajar ${textTitle}",
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
Column(
|
||||
|
@ -61,9 +71,9 @@ fun NavMaterialScreen(navController: NavController, materialId: String) {
|
|||
modifier = Modifier.fillMaxSize(),
|
||||
contentPadding = PaddingValues(16.dp)
|
||||
) {
|
||||
items(materialList) { chunk ->
|
||||
itemsIndexed(materialList) { index, chunk ->
|
||||
ConstraintLayout(modifier = Modifier.fillMaxWidth()) {
|
||||
val (space, boxItem, centerLine) = createRefs()
|
||||
val (space, boxItem, centerLine, lockIcon, cardIcon) = createRefs()
|
||||
Box(modifier = Modifier
|
||||
.background(color = cwhite, shape = RoundedCornerShape(12.dp))
|
||||
.constrainAs(boxItem) {
|
||||
|
@ -75,13 +85,15 @@ fun NavMaterialScreen(navController: NavController, materialId: String) {
|
|||
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(12.dp).clickable {
|
||||
println("testingkus")
|
||||
// val jsonList = Gson().toJson(chunk) // 🔥 Konversi List ke JSON String
|
||||
// navController.navigate("detailMaterial/$jsonList")
|
||||
navController.currentBackStackEntry?.savedStateHandle?.set("materialList", chunk)
|
||||
.padding(12.dp)
|
||||
.clickable {
|
||||
if (index <= (sizeUnlock ?: 0)) {
|
||||
navController.currentBackStackEntry?.savedStateHandle?.set(
|
||||
"materialList",
|
||||
chunk
|
||||
)
|
||||
navController.navigate("detailMaterial")
|
||||
|
||||
}
|
||||
},
|
||||
) {
|
||||
chunk.forEachIndexed { index, material ->
|
||||
|
@ -92,20 +104,64 @@ fun NavMaterialScreen(navController: NavController, materialId: String) {
|
|||
modifier = Modifier
|
||||
.size(80.dp) // 🔥 Ukuran gambar
|
||||
.clip(RoundedCornerShape(12.dp)) // 🔥 Memberikan sudut lengkung (radius)
|
||||
.border(2.dp, cGray, RoundedCornerShape(12.dp)) // 🔥 Memberikan border
|
||||
.border(
|
||||
2.dp,
|
||||
cGray,
|
||||
RoundedCornerShape(12.dp)
|
||||
) // 🔥 Memberikan border
|
||||
) {
|
||||
FirebaseImage(path = material.image, contentScale = ContentScale.Crop, modifier = Modifier.matchParentSize()) // 🔥 Pastikan gambar mengisi Box
|
||||
FirebaseImage(
|
||||
path = material.image,
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = Modifier.matchParentSize()
|
||||
) // 🔥 Pastikan gambar mengisi Box
|
||||
}
|
||||
Spacer(modifier = Modifier.height(50.dp))
|
||||
Text(text = "${material.enName}", color = cAccent, fontSize = 18.sp, fontWeight = FontWeight.Bold)
|
||||
Text(text = "${material.idName}", color = ctextGray, fontSize = 14.sp, fontWeight = FontWeight.Bold)
|
||||
Text(
|
||||
text = "${material.enName}",
|
||||
color = cAccent,
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
Text(
|
||||
text = "${material.idName}",
|
||||
color = ctextGray,
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Text(text = "${material.enName}", color = cAccent, fontSize = 18.sp, fontWeight = FontWeight.Bold)
|
||||
Text(text = "${material.idName}", color = ctextGray, fontSize = 14.sp, fontWeight = FontWeight.Bold)
|
||||
Text(
|
||||
text = "${material.enName}",
|
||||
color = cAccent,
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
Text(
|
||||
text = "${material.idName}",
|
||||
color = ctextGray,
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
Spacer(modifier = Modifier.height(50.dp))
|
||||
FirebaseImage(path = material.image, modifier = Modifier.size(80.dp))
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier
|
||||
.size(80.dp) // 🔥 Ukuran gambar
|
||||
.clip(RoundedCornerShape(12.dp)) // 🔥 Memberikan sudut lengkung (radius)
|
||||
.border(
|
||||
2.dp,
|
||||
cGray,
|
||||
RoundedCornerShape(12.dp)
|
||||
) // 🔥 Memberikan border
|
||||
) {
|
||||
FirebaseImage(
|
||||
path = material.image,
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = Modifier.matchParentSize()
|
||||
) // 🔥 Pastikan gambar mengisi Box
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,6 +183,25 @@ fun NavMaterialScreen(navController: NavController, materialId: String) {
|
|||
top.linkTo(boxItem.bottom)
|
||||
start.linkTo(boxItem.start)
|
||||
})
|
||||
if (index > (sizeUnlock ?: 0)) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.constrainAs(cardIcon) {
|
||||
start.linkTo(parent.start)
|
||||
top.linkTo(parent.top)
|
||||
bottom.linkTo(parent.bottom)
|
||||
end.linkTo(parent.end)
|
||||
}
|
||||
.background(Color.White.copy(alpha = 0.5f)) // Transparan blur effect
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Lock,
|
||||
contentDescription = "Lock Icon",
|
||||
modifier = Modifier.size(60.dp)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,12 @@ class NavMaterialViewModel(application: Application) : AndroidViewModel(applicat
|
|||
val isTTSInitialized: LiveData<Boolean> = _isTTSInitialized
|
||||
val alphabetList = generateNumberList()
|
||||
|
||||
private val _textTitle = MutableLiveData("Hello, Jetpack Compose!")
|
||||
val textTitle: LiveData<String> = _textTitle
|
||||
|
||||
private val _sizeUnlock = MutableLiveData(0)
|
||||
val sizeUnlock: LiveData<Int> = _sizeUnlock
|
||||
|
||||
private val repository = MaterialRepository(application)
|
||||
|
||||
private val _materialList = MutableStateFlow<List<List<MaterialDataModel>>>(emptyList())
|
||||
|
@ -29,9 +35,21 @@ class NavMaterialViewModel(application: Application) : AndroidViewModel(applicat
|
|||
|
||||
fun fetchMaterial(materialId: String) {
|
||||
viewModelScope.launch {
|
||||
repository.getMaterialData { materials ->
|
||||
val filteredMaterials = materials.filter { it.category == materialId }
|
||||
_materialList.value = filteredMaterials.chunked(3)
|
||||
repository.getUnlockValue(materialId) { value ->
|
||||
_sizeUnlock.value = value
|
||||
}
|
||||
repository.getMaterialData(materialId) { materials ->
|
||||
// val filteredMaterials = materials.filter { it.category == materialId }
|
||||
_materialList.value = materials.chunked(3)
|
||||
if (materials[0].category == "animal") {
|
||||
_textTitle.value = "hewan"
|
||||
} else if (materials[0].category == "limb") {
|
||||
_textTitle.value = "anggota tubuh"
|
||||
} else if (materials[0].category == "house") {
|
||||
_textTitle.value = "bagian rumah"
|
||||
} else if (materials[0].category == "family") {
|
||||
_textTitle.value = "anggota keluarga"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue