From 97c22c532540c1a0ca6f203abc46054aec79af66 Mon Sep 17 00:00:00 2001 From: DimazzP Date: Wed, 26 Feb 2025 09:10:00 +0700 Subject: [PATCH] update profile --- .../com/example/lexilearn/MainActivity.kt | 19 ++-- .../lexilearn/data/local/SharedPrefHelper.kt | 8 +- .../lexilearn/data/model/UserDataModel.kt | 5 +- .../lexilearn/data/remote/FirebaseHelper.kt | 86 ++++++++++++++++--- .../data/repository/MaterialRepository.kt | 32 +++---- .../lexilearn/ui/components/DialogProfile.kt | 64 ++++++++++++++ .../lexilearn/ui/views/pHome/HomeScreen.kt | 49 +++++++++-- .../lexilearn/ui/views/pHome/HomeViewModel.kt | 37 ++++++-- 8 files changed, 229 insertions(+), 71 deletions(-) create mode 100644 app/src/main/java/com/example/lexilearn/ui/components/DialogProfile.kt diff --git a/app/src/main/java/com/example/lexilearn/MainActivity.kt b/app/src/main/java/com/example/lexilearn/MainActivity.kt index 64f8c09..34caa95 100644 --- a/app/src/main/java/com/example/lexilearn/MainActivity.kt +++ b/app/src/main/java/com/example/lexilearn/MainActivity.kt @@ -13,7 +13,7 @@ import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument import com.example.lexilearn.data.model.MaterialDataModel -import com.example.lexilearn.data.model.UserModel +import com.example.lexilearn.data.model.UserDataModel import com.example.lexilearn.data.repository.MaterialRepository import com.example.lexilearn.ui.views.pDetailMaterial.DetailMaterialScreen import com.example.lexilearn.ui.views.pHome.HomeScreen @@ -36,12 +36,8 @@ class MainActivity : ComponentActivity() { 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 -> + repository.loginUser{ success, userId -> if (success) { Toast.makeText(this, "Login Berhasil! ID: $userId", Toast.LENGTH_SHORT).show() Log.d("MainActivity", "Login Berhasil! User ID: $userId") @@ -49,11 +45,10 @@ class MainActivity : ComponentActivity() { 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() + val newUser = UserDataModel( + name = "User", + age = 6, + unlock_data = UserDataModel.UnlockData() ) repository.createUser(newUser) { success, newUserId -> @@ -63,7 +58,7 @@ class MainActivity : ComponentActivity() { "User Baru Dibuat! Login Sekarang...", Toast.LENGTH_SHORT ).show() - repository.loginUser(email, password) { loginSuccess, loggedInUserId -> + repository.loginUser { loginSuccess, loggedInUserId -> if (loginSuccess) { Log.d( "MainActivity", diff --git a/app/src/main/java/com/example/lexilearn/data/local/SharedPrefHelper.kt b/app/src/main/java/com/example/lexilearn/data/local/SharedPrefHelper.kt index cb60d83..deaa381 100644 --- a/app/src/main/java/com/example/lexilearn/data/local/SharedPrefHelper.kt +++ b/app/src/main/java/com/example/lexilearn/data/local/SharedPrefHelper.kt @@ -3,7 +3,7 @@ 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.example.lexilearn.data.model.UserDataModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken @@ -77,16 +77,16 @@ class SharedPrefHelper(context: Context) { sharedPreferences.edit().clear().apply() } - fun getUserData(): UserModel? { + fun getUserData(): UserDataModel? { val json = sharedPreferences.getString("user_data", null) return if (json != null) { - Gson().fromJson(json, UserModel::class.java) + Gson().fromJson(json, UserDataModel::class.java) } else { null } } - fun saveUserData(user: UserModel) { + fun saveUserData(user: UserDataModel) { val editor = sharedPreferences.edit() val json = Gson().toJson(user) editor.putString("user_data", json) diff --git a/app/src/main/java/com/example/lexilearn/data/model/UserDataModel.kt b/app/src/main/java/com/example/lexilearn/data/model/UserDataModel.kt index c0ab315..de519af 100644 --- a/app/src/main/java/com/example/lexilearn/data/model/UserDataModel.kt +++ b/app/src/main/java/com/example/lexilearn/data/model/UserDataModel.kt @@ -1,9 +1,8 @@ package com.example.lexilearn.data.model -data class UserModel( - var email: String = "", +data class UserDataModel( var name: String = "", - var password: String = "", + var age: Int = 0, var unlock_data: UnlockData = UnlockData() // 🔥 Perbaiki cara mendeklarasikan UnlockData ) { data class UnlockData( diff --git a/app/src/main/java/com/example/lexilearn/data/remote/FirebaseHelper.kt b/app/src/main/java/com/example/lexilearn/data/remote/FirebaseHelper.kt index 7a8a21e..d21382a 100644 --- a/app/src/main/java/com/example/lexilearn/data/remote/FirebaseHelper.kt +++ b/app/src/main/java/com/example/lexilearn/data/remote/FirebaseHelper.kt @@ -5,7 +5,7 @@ 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.example.lexilearn.data.model.UserDataModel import com.google.firebase.database.* import com.google.firebase.database.DatabaseReference import com.google.firebase.database.FirebaseDatabase @@ -78,21 +78,45 @@ class FirebaseHelper(private val context: Context) { // ✅ 🔥 Fungsi Login - Mencari user berdasarkan email dan password - fun loginUser(email: String, password: String, callback: (Boolean, String?) -> Unit) { +// 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) +// } +// }) +// } + fun loginUser(callback: (Boolean, String?) -> Unit) { val databaseReference: DatabaseReference = FirebaseDatabase.getInstance().getReference("users") + val userId = sharedPrefHelper.getUserId() // Ambil ID pengguna yang disimpan di SharedPreferences - databaseReference.addListenerForSingleValueEvent(object : ValueEventListener { + if (userId.isNullOrEmpty()) { + callback(false, null) // Jika tidak ada ID tersimpan + return + } + + databaseReference.child(userId).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 - } + if (snapshot.exists()) { + callback(true, userId) + } else { + callback(false, null) // Jika user ID tidak ditemukan di database } - callback(false, null) // Jika tidak ditemukan } override fun onCancelled(error: DatabaseError) { @@ -102,8 +126,42 @@ class FirebaseHelper(private val context: Context) { }) } + fun createUser(user: UserDataModel, callback: (Boolean, String?) -> Unit) { + val databaseReference = FirebaseDatabase.getInstance().getReference("users") + + 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 updateUser(updatedUser: UserDataModel, callback: (Boolean) -> Unit) { + val getUserData = sharedPrefHelper.getUserData() + val userId = sharedPrefHelper.getUserId() // Ambil ID pengguna yang disimpan di SharedPreferences + val databaseReference = FirebaseDatabase.getInstance().getReference("users") + val newData = mapOf( + "name" to updatedUser.name, + "age" to updatedUser.age, + ) + if(userId!=null){ + databaseReference.child(userId).updateChildren(newData).addOnCompleteListener { task -> + callback(task.isSuccessful) + } + } + } + // ✅ 🔥 Fungsi Fetch User Data Berdasarkan ID (Dapatkan data user setelah login) - fun fetchUserData(callback: (UserModel?) -> Unit) { + fun fetchUserData(callback: (UserDataModel?) -> Unit) { val userId = sharedPrefHelper.getUserId() if (userId == null) { @@ -115,7 +173,7 @@ class FirebaseHelper(private val context: Context) { databaseReference.addListenerForSingleValueEvent(object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { - val user = snapshot.getValue(UserModel::class.java) + val user = snapshot.getValue(UserDataModel::class.java) callback(user) } diff --git a/app/src/main/java/com/example/lexilearn/data/repository/MaterialRepository.kt b/app/src/main/java/com/example/lexilearn/data/repository/MaterialRepository.kt index 351e4d8..c7f29de 100644 --- a/app/src/main/java/com/example/lexilearn/data/repository/MaterialRepository.kt +++ b/app/src/main/java/com/example/lexilearn/data/repository/MaterialRepository.kt @@ -4,7 +4,7 @@ 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.example.lexilearn.data.model.UserDataModel import com.google.firebase.database.FirebaseDatabase class MaterialRepository(private val context: Context) { @@ -43,28 +43,16 @@ class MaterialRepository(private val context: Context) { } } - 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 updateUser(updatedUser: UserDataModel, callback: (Boolean) -> Unit) { + firebaseHelper.updateUser(updatedUser, callback) } - fun loginUser(email: String, password: String, callback: (Boolean, String?) -> Unit) { - firebaseHelper.loginUser(email, password) { success, userId -> + fun createUser(user: UserDataModel, callback: (Boolean, String?) -> Unit) { + firebaseHelper.createUser(user, callback) + } + + fun loginUser( callback: (Boolean, String?) -> Unit) { + firebaseHelper.loginUser{ success, userId -> if (success && userId != null) { sharedPrefHelper.saveUserId(userId) // Simpan ID user callback(true, userId) @@ -74,7 +62,7 @@ class MaterialRepository(private val context: Context) { } } - fun getUserData(callback: (UserModel?) -> Unit) { + fun getUserData(callback: (UserDataModel?) -> Unit) { firebaseHelper.fetchUserData { user -> callback(user) } diff --git a/app/src/main/java/com/example/lexilearn/ui/components/DialogProfile.kt b/app/src/main/java/com/example/lexilearn/ui/components/DialogProfile.kt new file mode 100644 index 0000000..3ed318b --- /dev/null +++ b/app/src/main/java/com/example/lexilearn/ui/components/DialogProfile.kt @@ -0,0 +1,64 @@ +package com.example.lexilearn.ui.components + +import android.widget.Toast +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.unit.dp +import com.example.lexilearn.data.model.UserDataModel +import com.example.lexilearn.data.repository.MaterialRepository + +@Composable +fun DialogProfile(showDialog: Boolean, repository: MaterialRepository, userData: UserDataModel, onDismiss: () -> Unit) { + val context = LocalContext.current + var name by remember { mutableStateOf(TextFieldValue(userData.name)) } + var age by remember { mutableStateOf(TextFieldValue(userData.age.toString())) } + + if (showDialog) { + AlertDialog( + onDismissRequest = { onDismiss() }, + title = { Text("Isikan Data Diri") }, + text = { + Column { + Text("Masukkan Nama") + TextField( + value = name, + onValueChange = { name = it }, + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(8.dp) + ) + Spacer(modifier = Modifier.height(8.dp)) + Text("Masukkan Usia") + TextField( + value = age, + onValueChange = { age = it }, + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(8.dp), + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number) + ) + } + }, + confirmButton = { + Button(onClick = { + repository.updateUser(UserDataModel(name.text, age.text.toInt(), userData.unlock_data)){ + onDismiss() + Toast.makeText(context, "Data Pengguna Diperbarui", Toast.LENGTH_LONG).show() + } + }) { + Text("Simpan") + } + }, + dismissButton = { + Button(onClick = { onDismiss() }) { + Text("Batal") + } + } + ) + } +} diff --git a/app/src/main/java/com/example/lexilearn/ui/views/pHome/HomeScreen.kt b/app/src/main/java/com/example/lexilearn/ui/views/pHome/HomeScreen.kt index 90ab3ee..4de1b9b 100644 --- a/app/src/main/java/com/example/lexilearn/ui/views/pHome/HomeScreen.kt +++ b/app/src/main/java/com/example/lexilearn/ui/views/pHome/HomeScreen.kt @@ -16,11 +16,12 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -42,6 +43,7 @@ import androidx.navigation.NavController import com.example.lexilearn.R import com.example.lexilearn.ui.components.AutoSizeText import com.example.lexilearn.ui.components.ButtonHome +import com.example.lexilearn.ui.components.DialogProfile import com.example.lexilearn.ui.theme.cAccent import com.example.lexilearn.ui.theme.cGray import com.example.lexilearn.ui.theme.cTextPrimary @@ -56,6 +58,8 @@ import com.example.lexilearn.ui.theme.cwhite fun HomeScreen(navController: NavController, viewModel: HomeViewModel = viewModel()) { val scrollState = rememberScrollState() val competitionScore = viewModel.topScores.collectAsState() + val showDialogProfile = viewModel.dialogProfile.collectAsState() + val userData = viewModel.userData.collectAsState() Column( modifier = Modifier @@ -72,20 +76,36 @@ fun HomeScreen(navController: NavController, viewModel: HomeViewModel = viewMode modifier = Modifier .fillMaxWidth() ) { - val (titleRef, dateRef) = createRefs() + val (titleRef, dateRef, buttonRef) = createRefs() Text( - text = "Name", + text = "${userData.value?.name}", fontSize = 20.sp, fontWeight = FontWeight.SemiBold, color = ctextBlack, - modifier = Modifier.constrainAs(titleRef) { - top.linkTo(parent.top, margin = 24.dp) - start.linkTo(parent.start, margin = 16.dp) - bottom.linkTo(parent.bottom, margin = 24.dp) - } + modifier = Modifier + .constrainAs(titleRef) { + top.linkTo(parent.top, margin = 16.dp) + start.linkTo(parent.start, margin = 16.dp) + bottom.linkTo(parent.bottom, margin = 24.dp) + } ) + IconButton(onClick = { + viewModel.showHiddenDialog() + }, modifier = Modifier.constrainAs(buttonRef) { + end.linkTo(parent.end, margin = 16.dp) + top.linkTo(titleRef.top) + }) { + Icon( + painter = painterResource(id = R.drawable.ic_setting), + tint = ctextWhite, + contentDescription = null, + modifier = Modifier + .width(30.dp) + .height(30.dp) + ) + } Text( - text = "Selamat Datang", + text = "${userData.value?.age} tahun", fontSize = 14.sp, color = ctextWhite, modifier = Modifier.constrainAs(dateRef) { @@ -94,6 +114,7 @@ fun HomeScreen(navController: NavController, viewModel: HomeViewModel = viewMode } ) } + Spacer(modifier = Modifier.height(6.dp)) Box( modifier = Modifier .fillMaxWidth() @@ -397,5 +418,15 @@ fun HomeScreen(navController: NavController, viewModel: HomeViewModel = viewMode } } } + if(userData.value!=null){ + DialogProfile( + showDialog = showDialogProfile.value, + repository = viewModel.materialRepository, + userData = userData.value!! + ) { + viewModel.showHiddenDialog() + viewModel.getUserData() + } + } } } diff --git a/app/src/main/java/com/example/lexilearn/ui/views/pHome/HomeViewModel.kt b/app/src/main/java/com/example/lexilearn/ui/views/pHome/HomeViewModel.kt index 2577c40..f7edfe0 100644 --- a/app/src/main/java/com/example/lexilearn/ui/views/pHome/HomeViewModel.kt +++ b/app/src/main/java/com/example/lexilearn/ui/views/pHome/HomeViewModel.kt @@ -3,12 +3,10 @@ package com.example.lexilearn.ui.views.pHome import android.app.Application import android.util.Log import androidx.lifecycle.AndroidViewModel -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import com.example.lexilearn.data.model.CompetitionScore import com.example.lexilearn.data.model.MaterialDataModel -import com.example.lexilearn.data.model.QuizState +import com.example.lexilearn.data.model.UserDataModel import com.example.lexilearn.data.repository.MaterialRepository import com.example.lexilearn.data.repository.QuizRepository import com.google.firebase.database.DataSnapshot @@ -16,9 +14,11 @@ import com.google.firebase.database.DatabaseError import com.google.firebase.database.DatabaseReference import com.google.firebase.database.FirebaseDatabase import com.google.firebase.database.ValueEventListener +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch import java.text.SimpleDateFormat import java.util.Date import java.util.Locale @@ -27,14 +27,21 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) { private val totalDataCompetition = 3 - private val _materialRepository = MaterialRepository(application) + val materialRepository = MaterialRepository(application) private val _quizRepository = QuizRepository() - private val database: DatabaseReference = FirebaseDatabase.getInstance().getReference("competitions") + private val _dialogProfile = MutableStateFlow(false) + val dialogProfile: StateFlow get() = _dialogProfile.asStateFlow() + + private val database: DatabaseReference = + FirebaseDatabase.getInstance().getReference("competitions") private val _topScores = MutableStateFlow>(emptyList()) val topScores: StateFlow> get() = _topScores.asStateFlow() + val _userData = MutableStateFlow(null) + val userData = _userData.asStateFlow() + // 🔥 Mendapatkan tanggal hari ini dalam format "dd-MM-yyyy" private fun getTodayDate(): String { val dateFormat = SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()) @@ -43,8 +50,20 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) { init { fetchTop10Scores() + getUserData() } + + fun getUserData() { + viewModelScope.launch { + delay(3000) + materialRepository.getUserData { data -> + _userData.value = data + } + } + } + + // 🔥 Fungsi untuk mengambil 10 skor tertinggi secara real-time dari Firebase fun fetchTop10Scores() { val todayDate = getTodayDate() @@ -71,11 +90,15 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) { } fun prepareCompetitionQuiz(callback: (List) -> Unit) { - _materialRepository.getAllMaterialData("all") { materials -> + materialRepository.getAllMaterialData("all") { materials -> _quizRepository.getRandomMaterials(totalDataCompetition, materials) { randomData -> randomData.forEach { println(it) } callback(randomData) } } } + + fun showHiddenDialog() { + _dialogProfile.value = !_dialogProfile.value + } } \ No newline at end of file