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.compose.rememberNavController
import androidx.navigation.navArgument 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.UserDataModel
import com.example.lexilearn.data.repository.MaterialRepository import com.example.lexilearn.data.repository.MaterialRepository
import com.example.lexilearn.ui.views.pDetailMaterial.DetailMaterialScreen import com.example.lexilearn.ui.views.pDetailMaterial.DetailMaterialScreen
import com.example.lexilearn.ui.views.pHome.HomeScreen import com.example.lexilearn.ui.views.pHome.HomeScreen
@ -36,12 +36,8 @@ class MainActivity : ComponentActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val repository = MaterialRepository(this) val repository = MaterialRepository(this)
// 🔥 Default email & password
val email = "example@gmail.com"
val password = "example123"
// 🔥 Coba login // 🔥 Coba login
repository.loginUser(email, password) { success, userId -> repository.loginUser{ success, userId ->
if (success) { if (success) {
Toast.makeText(this, "Login Berhasil! ID: $userId", Toast.LENGTH_SHORT).show() Toast.makeText(this, "Login Berhasil! ID: $userId", Toast.LENGTH_SHORT).show()
Log.d("MainActivity", "Login Berhasil! User ID: $userId") Log.d("MainActivity", "Login Berhasil! User ID: $userId")
@ -49,11 +45,10 @@ class MainActivity : ComponentActivity() {
Log.e("MainActivity", "User tidak ditemukan, membuat akun baru...") Log.e("MainActivity", "User tidak ditemukan, membuat akun baru...")
// 🔥 Jika tidak ditemukan, buat user baru // 🔥 Jika tidak ditemukan, buat user baru
val newUser = UserModel( val newUser = UserDataModel(
email = email, name = "User",
name = "Example User", age = 6,
password = password, unlock_data = UserDataModel.UnlockData()
unlock_data = UserModel.UnlockData()
) )
repository.createUser(newUser) { success, newUserId -> repository.createUser(newUser) { success, newUserId ->
@ -63,7 +58,7 @@ class MainActivity : ComponentActivity() {
"User Baru Dibuat! Login Sekarang...", "User Baru Dibuat! Login Sekarang...",
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
repository.loginUser(email, password) { loginSuccess, loggedInUserId -> repository.loginUser { loginSuccess, loggedInUserId ->
if (loginSuccess) { if (loginSuccess) {
Log.d( Log.d(
"MainActivity", "MainActivity",

View File

@ -3,7 +3,7 @@ package com.example.lexilearn.data.local
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
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.UserDataModel
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
@ -77,16 +77,16 @@ class SharedPrefHelper(context: Context) {
sharedPreferences.edit().clear().apply() sharedPreferences.edit().clear().apply()
} }
fun getUserData(): UserModel? { fun getUserData(): UserDataModel? {
val json = sharedPreferences.getString("user_data", null) val json = sharedPreferences.getString("user_data", null)
return if (json != null) { return if (json != null) {
Gson().fromJson(json, UserModel::class.java) Gson().fromJson(json, UserDataModel::class.java)
} else { } else {
null null
} }
} }
fun saveUserData(user: UserModel) { fun saveUserData(user: UserDataModel) {
val editor = sharedPreferences.edit() val editor = sharedPreferences.edit()
val json = Gson().toJson(user) val json = Gson().toJson(user)
editor.putString("user_data", json) editor.putString("user_data", json)

View File

@ -1,9 +1,8 @@
package com.example.lexilearn.data.model package com.example.lexilearn.data.model
data class UserModel( data class UserDataModel(
var email: String = "",
var name: String = "", var name: String = "",
var password: String = "", var age: Int = 0,
var unlock_data: UnlockData = UnlockData() // 🔥 Perbaiki cara mendeklarasikan UnlockData var unlock_data: UnlockData = UnlockData() // 🔥 Perbaiki cara mendeklarasikan UnlockData
) { ) {
data class UnlockData( data class UnlockData(

View File

@ -5,7 +5,7 @@ import android.content.Context
import android.util.Log import android.util.Log
import com.example.lexilearn.data.model.MaterialDataModel import com.example.lexilearn.data.model.MaterialDataModel
import com.example.lexilearn.data.local.SharedPrefHelper 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.*
import com.google.firebase.database.DatabaseReference import com.google.firebase.database.DatabaseReference
import com.google.firebase.database.FirebaseDatabase import com.google.firebase.database.FirebaseDatabase
@ -78,21 +78,45 @@ class FirebaseHelper(private val context: Context) {
// ✅ 🔥 Fungsi Login - Mencari user berdasarkan email dan password // ✅ 🔥 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 databaseReference: DatabaseReference = FirebaseDatabase.getInstance().getReference("users")
val userId = sharedPrefHelper.getUserId() // Ambil ID pengguna yang disimpan di SharedPreferences
databaseReference.addListenerForSingleValueEvent(object : ValueEventListener { if (userId.isNullOrEmpty()) {
override fun onDataChange(snapshot: DataSnapshot) { callback(false, null) // Jika tidak ada ID tersimpan
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 return
} }
databaseReference.child(userId).addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
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) { 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) // ✅ 🔥 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() val userId = sharedPrefHelper.getUserId()
if (userId == null) { if (userId == null) {
@ -115,7 +173,7 @@ class FirebaseHelper(private val context: Context) {
databaseReference.addListenerForSingleValueEvent(object : ValueEventListener { databaseReference.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) { override fun onDataChange(snapshot: DataSnapshot) {
val user = snapshot.getValue(UserModel::class.java) val user = snapshot.getValue(UserDataModel::class.java)
callback(user) callback(user)
} }

View File

@ -4,7 +4,7 @@ import android.content.Context
import com.example.lexilearn.data.local.SharedPrefHelper import com.example.lexilearn.data.local.SharedPrefHelper
import com.example.lexilearn.data.remote.FirebaseHelper import com.example.lexilearn.data.remote.FirebaseHelper
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.UserDataModel
import com.google.firebase.database.FirebaseDatabase import com.google.firebase.database.FirebaseDatabase
class MaterialRepository(private val context: Context) { class MaterialRepository(private val context: Context) {
@ -43,28 +43,16 @@ class MaterialRepository(private val context: Context) {
} }
} }
fun createUser(user: UserModel, callback: (Boolean, String?) -> Unit) { fun updateUser(updatedUser: UserDataModel, callback: (Boolean) -> Unit) {
val databaseReference = FirebaseDatabase.getInstance().getReference("users") firebaseHelper.updateUser(updatedUser, callback)
// 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) { fun createUser(user: UserDataModel, callback: (Boolean, String?) -> Unit) {
firebaseHelper.loginUser(email, password) { success, userId -> firebaseHelper.createUser(user, callback)
}
fun loginUser( callback: (Boolean, String?) -> Unit) {
firebaseHelper.loginUser{ success, userId ->
if (success && userId != null) { if (success && userId != null) {
sharedPrefHelper.saveUserId(userId) // Simpan ID user sharedPrefHelper.saveUserId(userId) // Simpan ID user
callback(true, userId) 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 -> firebaseHelper.fetchUserData { user ->
callback(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.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
@ -42,6 +43,7 @@ import androidx.navigation.NavController
import com.example.lexilearn.R import com.example.lexilearn.R
import com.example.lexilearn.ui.components.AutoSizeText import com.example.lexilearn.ui.components.AutoSizeText
import com.example.lexilearn.ui.components.ButtonHome 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.cAccent
import com.example.lexilearn.ui.theme.cGray import com.example.lexilearn.ui.theme.cGray
import com.example.lexilearn.ui.theme.cTextPrimary 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()) { fun HomeScreen(navController: NavController, viewModel: HomeViewModel = viewModel()) {
val scrollState = rememberScrollState() val scrollState = rememberScrollState()
val competitionScore = viewModel.topScores.collectAsState() val competitionScore = viewModel.topScores.collectAsState()
val showDialogProfile = viewModel.dialogProfile.collectAsState()
val userData = viewModel.userData.collectAsState()
Column( Column(
modifier = Modifier modifier = Modifier
@ -72,20 +76,36 @@ fun HomeScreen(navController: NavController, viewModel: HomeViewModel = viewMode
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
) { ) {
val (titleRef, dateRef) = createRefs() val (titleRef, dateRef, buttonRef) = createRefs()
Text( Text(
text = "Name", text = "${userData.value?.name}",
fontSize = 20.sp, fontSize = 20.sp,
fontWeight = FontWeight.SemiBold, fontWeight = FontWeight.SemiBold,
color = ctextBlack, color = ctextBlack,
modifier = Modifier.constrainAs(titleRef) { modifier = Modifier
top.linkTo(parent.top, margin = 24.dp) .constrainAs(titleRef) {
top.linkTo(parent.top, margin = 16.dp)
start.linkTo(parent.start, margin = 16.dp) start.linkTo(parent.start, margin = 16.dp)
bottom.linkTo(parent.bottom, margin = 24.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(
text = "Selamat Datang", text = "${userData.value?.age} tahun",
fontSize = 14.sp, fontSize = 14.sp,
color = ctextWhite, color = ctextWhite,
modifier = Modifier.constrainAs(dateRef) { modifier = Modifier.constrainAs(dateRef) {
@ -94,6 +114,7 @@ fun HomeScreen(navController: NavController, viewModel: HomeViewModel = viewMode
} }
) )
} }
Spacer(modifier = Modifier.height(6.dp))
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .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.app.Application
import android.util.Log import android.util.Log
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData import androidx.lifecycle.viewModelScope
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.example.lexilearn.data.model.CompetitionScore import com.example.lexilearn.data.model.CompetitionScore
import com.example.lexilearn.data.model.MaterialDataModel 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.MaterialRepository
import com.example.lexilearn.data.repository.QuizRepository import com.example.lexilearn.data.repository.QuizRepository
import com.google.firebase.database.DataSnapshot 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.DatabaseReference
import com.google.firebase.database.FirebaseDatabase import com.google.firebase.database.FirebaseDatabase
import com.google.firebase.database.ValueEventListener import com.google.firebase.database.ValueEventListener
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
@ -27,14 +27,21 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) {
private val totalDataCompetition = 3 private val totalDataCompetition = 3
private val _materialRepository = MaterialRepository(application) val materialRepository = MaterialRepository(application)
private val _quizRepository = QuizRepository() 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()) private val _topScores = MutableStateFlow<List<CompetitionScore>>(emptyList())
val topScores: StateFlow<List<CompetitionScore>> get() = _topScores.asStateFlow() 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" // 🔥 Mendapatkan tanggal hari ini dalam format "dd-MM-yyyy"
private fun getTodayDate(): String { private fun getTodayDate(): String {
val dateFormat = SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()) val dateFormat = SimpleDateFormat("dd-MM-yyyy", Locale.getDefault())
@ -43,8 +50,20 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) {
init { init {
fetchTop10Scores() 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 // 🔥 Fungsi untuk mengambil 10 skor tertinggi secara real-time dari Firebase
fun fetchTop10Scores() { fun fetchTop10Scores() {
val todayDate = getTodayDate() val todayDate = getTodayDate()
@ -71,11 +90,15 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) {
} }
fun prepareCompetitionQuiz(callback: (List<MaterialDataModel>) -> Unit) { fun prepareCompetitionQuiz(callback: (List<MaterialDataModel>) -> Unit) {
_materialRepository.getAllMaterialData("all") { materials -> materialRepository.getAllMaterialData("all") { materials ->
_quizRepository.getRandomMaterials(totalDataCompetition, materials) { randomData -> _quizRepository.getRandomMaterials(totalDataCompetition, materials) { randomData ->
randomData.forEach { println(it) } randomData.forEach { println(it) }
callback(randomData) callback(randomData)
} }
} }
} }
fun showHiddenDialog() {
_dialogProfile.value = !_dialogProfile.value
}
} }