update profile

This commit is contained in:
DimazzP 2025-02-26 09:10:00 +07:00
parent 940378ce37
commit 97c22c5325
8 changed files with 229 additions and 71 deletions

View File

@ -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",

View File

@ -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)

View File

@ -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(

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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")
}
}
)
}
}

View File

@ -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()
}
}
}
}

View File

@ -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<Boolean>(false)
val dialogProfile: StateFlow<Boolean> get() = _dialogProfile.asStateFlow()
private val database: DatabaseReference =
FirebaseDatabase.getInstance().getReference("competitions")
private val _topScores = MutableStateFlow<List<CompetitionScore>>(emptyList())
val topScores: StateFlow<List<CompetitionScore>> get() = _topScores.asStateFlow()
val _userData = MutableStateFlow<UserDataModel?>(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<MaterialDataModel>) -> 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
}
}