mirror of
https://github.com/shaulascr/ecommerce_serang.git
synced 2025-08-13 10:42:21 +00:00
call detail product and profile
This commit is contained in:
@ -5,7 +5,7 @@ import com.google.gson.annotations.SerializedName
|
|||||||
data class UserProfile(
|
data class UserProfile(
|
||||||
|
|
||||||
@field:SerializedName("image")
|
@field:SerializedName("image")
|
||||||
val image: Any?,
|
val image: String? = null,
|
||||||
|
|
||||||
@field:SerializedName("role")
|
@field:SerializedName("role")
|
||||||
val role: String,
|
val role: String,
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
package com.alya.ecommerce_serang.data.api.response
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
data class AllStoreResponse(
|
||||||
|
|
||||||
|
@field:SerializedName("store")
|
||||||
|
val store: AllStore,
|
||||||
|
|
||||||
|
@field:SerializedName("message")
|
||||||
|
val message: String
|
||||||
|
)
|
||||||
|
|
||||||
|
data class AllStore(
|
||||||
|
|
||||||
|
@field:SerializedName("store_name")
|
||||||
|
val storeName: String,
|
||||||
|
|
||||||
|
@field:SerializedName("description")
|
||||||
|
val description: String,
|
||||||
|
|
||||||
|
@field:SerializedName("store_type")
|
||||||
|
val storeType: String,
|
||||||
|
|
||||||
|
@field:SerializedName("store_location")
|
||||||
|
val storeLocation: String,
|
||||||
|
|
||||||
|
@field:SerializedName("store_image")
|
||||||
|
val storeImage: Any,
|
||||||
|
|
||||||
|
@field:SerializedName("status")
|
||||||
|
val status: String
|
||||||
|
)
|
@ -0,0 +1,33 @@
|
|||||||
|
package com.alya.ecommerce_serang.data.api.response
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
data class DetailStoreProductResponse(
|
||||||
|
|
||||||
|
@field:SerializedName("store")
|
||||||
|
val store: StoreProduct,
|
||||||
|
|
||||||
|
@field:SerializedName("message")
|
||||||
|
val message: String
|
||||||
|
)
|
||||||
|
|
||||||
|
data class StoreProduct(
|
||||||
|
|
||||||
|
@field:SerializedName("store_name")
|
||||||
|
val storeName: String,
|
||||||
|
|
||||||
|
@field:SerializedName("description")
|
||||||
|
val description: String,
|
||||||
|
|
||||||
|
@field:SerializedName("store_type")
|
||||||
|
val storeType: String,
|
||||||
|
|
||||||
|
@field:SerializedName("store_location")
|
||||||
|
val storeLocation: String,
|
||||||
|
|
||||||
|
@field:SerializedName("store_image")
|
||||||
|
val storeImage: Any,
|
||||||
|
|
||||||
|
@field:SerializedName("status")
|
||||||
|
val status: String
|
||||||
|
)
|
@ -17,7 +17,7 @@ data class Product(
|
|||||||
val storeId: Int,
|
val storeId: Int,
|
||||||
|
|
||||||
@field:SerializedName("image")
|
@field:SerializedName("image")
|
||||||
val image: String,
|
val image: String? = null,
|
||||||
|
|
||||||
@field:SerializedName("rating")
|
@field:SerializedName("rating")
|
||||||
val rating: String,
|
val rating: String,
|
||||||
|
@ -8,6 +8,7 @@ import com.alya.ecommerce_serang.data.api.response.CategoryResponse
|
|||||||
import com.alya.ecommerce_serang.data.api.response.LoginResponse
|
import com.alya.ecommerce_serang.data.api.response.LoginResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.OtpResponse
|
import com.alya.ecommerce_serang.data.api.response.OtpResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.ProductResponse
|
import com.alya.ecommerce_serang.data.api.response.ProductResponse
|
||||||
|
import com.alya.ecommerce_serang.data.api.response.ProfileResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.RegisterResponse
|
import com.alya.ecommerce_serang.data.api.response.RegisterResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.ReviewProductResponse
|
import com.alya.ecommerce_serang.data.api.response.ReviewProductResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.StoreResponse
|
import com.alya.ecommerce_serang.data.api.response.StoreResponse
|
||||||
@ -51,6 +52,10 @@ interface ApiService {
|
|||||||
@Path("id") productId: Int
|
@Path("id") productId: Int
|
||||||
): Response<ProductResponse>
|
): Response<ProductResponse>
|
||||||
|
|
||||||
|
@GET("profile")
|
||||||
|
suspend fun getUserProfile(): Response<ProfileResponse>
|
||||||
|
|
||||||
|
|
||||||
@GET("mystore")
|
@GET("mystore")
|
||||||
fun getStore (): Call<StoreResponse>
|
fun getStore (): Call<StoreResponse>
|
||||||
}
|
}
|
@ -37,6 +37,7 @@ class ProductRepository(private val apiService: ApiService) {
|
|||||||
if (response.isSuccessful) {
|
if (response.isSuccessful) {
|
||||||
response.body()
|
response.body()
|
||||||
} else {
|
} else {
|
||||||
|
Log.e("ProductRepository", "Error: ${response.errorBody()?.string()}")
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@ -70,6 +71,7 @@ class ProductRepository(private val apiService: ApiService) {
|
|||||||
if (response.isSuccessful) {
|
if (response.isSuccessful) {
|
||||||
response.body()?.reviews // Ambil daftar review dari response
|
response.body()?.reviews // Ambil daftar review dari response
|
||||||
} else {
|
} else {
|
||||||
|
Log.e("ProductRepository", "Error: ${response.errorBody()?.string()}")
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
@ -3,6 +3,7 @@ package com.alya.ecommerce_serang.data.repository
|
|||||||
import com.alya.ecommerce_serang.data.api.dto.LoginRequest
|
import com.alya.ecommerce_serang.data.api.dto.LoginRequest
|
||||||
import com.alya.ecommerce_serang.data.api.dto.OtpRequest
|
import com.alya.ecommerce_serang.data.api.dto.OtpRequest
|
||||||
import com.alya.ecommerce_serang.data.api.dto.RegisterRequest
|
import com.alya.ecommerce_serang.data.api.dto.RegisterRequest
|
||||||
|
import com.alya.ecommerce_serang.data.api.dto.UserProfile
|
||||||
import com.alya.ecommerce_serang.data.api.response.LoginResponse
|
import com.alya.ecommerce_serang.data.api.response.LoginResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.OtpResponse
|
import com.alya.ecommerce_serang.data.api.response.OtpResponse
|
||||||
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
|
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
|
||||||
@ -42,6 +43,23 @@ class UserRepository(private val apiService: ApiService) {
|
|||||||
Result.Error(e)
|
Result.Error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun fetchUserProfile(): Result<UserProfile?> {
|
||||||
|
return try {
|
||||||
|
val response = apiService.getUserProfile()
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
response.body()?.user?.let {
|
||||||
|
Result.Success(it) // ✅ Returning only UserProfile
|
||||||
|
} ?: Result.Error(Exception("User data not found"))
|
||||||
|
} else {
|
||||||
|
Result.Error(Exception("Error fetching profile: ${response.code()}"))
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Result.Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class Result<out T> {
|
sealed class Result<out T> {
|
||||||
|
@ -107,7 +107,7 @@ class HomeFragment : Fragment() {
|
|||||||
binding.loading.root.isVisible = false
|
binding.loading.root.isVisible = false
|
||||||
binding.error.root.isVisible = false
|
binding.error.root.isVisible = false
|
||||||
binding.home.isVisible = true
|
binding.home.isVisible = true
|
||||||
productAdapter?.updateLimitedProducts(state.products)
|
productAdapter?.updateLimitedProducts(state.products) // Ensure productAdapter is initialized
|
||||||
}
|
}
|
||||||
is HomeUiState.Error -> {
|
is HomeUiState.Error -> {
|
||||||
binding.loading.root.isVisible = false
|
binding.loading.root.isVisible = false
|
||||||
|
@ -4,13 +4,16 @@ import android.os.Bundle
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import com.alya.ecommerce_serang.BuildConfig.BASE_URL
|
||||||
|
import com.alya.ecommerce_serang.R
|
||||||
|
import com.alya.ecommerce_serang.data.api.response.Product
|
||||||
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
|
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
|
||||||
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
|
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
|
||||||
import com.alya.ecommerce_serang.data.repository.ProductRepository
|
import com.alya.ecommerce_serang.data.repository.ProductRepository
|
||||||
import com.alya.ecommerce_serang.databinding.ActivityDetailProductBinding
|
import com.alya.ecommerce_serang.databinding.ActivityDetailProductBinding
|
||||||
import com.alya.ecommerce_serang.ui.home.HomeViewModel
|
|
||||||
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
||||||
import com.alya.ecommerce_serang.utils.SessionManager
|
import com.alya.ecommerce_serang.utils.SessionManager
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
|
||||||
class DetailProductActivity : AppCompatActivity() {
|
class DetailProductActivity : AppCompatActivity() {
|
||||||
private lateinit var binding: ActivityDetailProductBinding
|
private lateinit var binding: ActivityDetailProductBinding
|
||||||
@ -21,7 +24,7 @@ class DetailProductActivity : AppCompatActivity() {
|
|||||||
BaseViewModelFactory {
|
BaseViewModelFactory {
|
||||||
val apiService = ApiConfig.getApiService(sessionManager)
|
val apiService = ApiConfig.getApiService(sessionManager)
|
||||||
val productRepository = ProductRepository(apiService)
|
val productRepository = ProductRepository(apiService)
|
||||||
HomeViewModel(productRepository)
|
ProductViewModel(productRepository)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@ -51,6 +54,21 @@ class DetailProductActivity : AppCompatActivity() {
|
|||||||
if (product != null) {
|
if (product != null) {
|
||||||
Log.d("ProductDetail", "Name: ${product.productName}, Price: ${product.price}")
|
Log.d("ProductDetail", "Name: ${product.productName}, Price: ${product.price}")
|
||||||
// Update UI here, e.g., show in a TextView or ImageView
|
// Update UI here, e.g., show in a TextView or ImageView
|
||||||
|
viewModel.loadProductDetail(productId)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Log.e("ProductDetail", "Failed to fetch product details")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
observeProductDetail()
|
||||||
|
}
|
||||||
|
private fun observeProductDetail() {
|
||||||
|
viewModel.productDetail.observe(this) { product ->
|
||||||
|
product?.let { updateUI(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateUI(product: Product){
|
||||||
binding.tvProductName.text = product.productName
|
binding.tvProductName.text = product.productName
|
||||||
binding.tvPrice.text = product.price
|
binding.tvPrice.text = product.price
|
||||||
binding.tvSold.text = product.totalSold.toString()
|
binding.tvSold.text = product.totalSold.toString()
|
||||||
@ -61,11 +79,17 @@ class DetailProductActivity : AppCompatActivity() {
|
|||||||
binding.tvDescription.text = product.description
|
binding.tvDescription.text = product.description
|
||||||
binding.tvSellerName.text = product.storeId.toString()
|
binding.tvSellerName.text = product.storeId.toString()
|
||||||
|
|
||||||
|
val fullImageUrl = when (val img = product.image) {
|
||||||
|
is String -> {
|
||||||
|
if (img.startsWith("/")) BASE_URL + img.substring(1) else img
|
||||||
|
}
|
||||||
|
else -> R.drawable.placeholder_image // Default image for null
|
||||||
|
}
|
||||||
|
Log.d("ProductAdapter", "Loading image: $fullImageUrl")
|
||||||
|
|
||||||
} else {
|
Glide.with(this)
|
||||||
Log.e("ProductDetail", "Failed to fetch product details")
|
.load(fullImageUrl)
|
||||||
}
|
.placeholder(R.drawable.placeholder_image)
|
||||||
}
|
.into(binding.ivProductImage)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,21 +1,85 @@
|
|||||||
package com.alya.ecommerce_serang.ui.profile
|
package com.alya.ecommerce_serang.ui.profile
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
|
import androidx.activity.viewModels
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.view.ViewCompat
|
import com.alya.ecommerce_serang.data.api.dto.UserProfile
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
|
||||||
import com.alya.ecommerce_serang.R
|
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
|
||||||
|
import com.alya.ecommerce_serang.data.repository.UserRepository
|
||||||
|
import com.alya.ecommerce_serang.databinding.ActivityDetailProfileBinding
|
||||||
|
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
||||||
|
import com.alya.ecommerce_serang.utils.SessionManager
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Locale
|
||||||
|
import java.util.TimeZone
|
||||||
|
|
||||||
class DetailProfileActivity : AppCompatActivity() {
|
class DetailProfileActivity : AppCompatActivity() {
|
||||||
|
private lateinit var binding: ActivityDetailProfileBinding
|
||||||
|
private lateinit var apiService: ApiService
|
||||||
|
private lateinit var sessionManager: SessionManager
|
||||||
|
|
||||||
|
private val viewModel: ProfileViewModel by viewModels {
|
||||||
|
BaseViewModelFactory {
|
||||||
|
val apiService = ApiConfig.getApiService(sessionManager)
|
||||||
|
val userRepository = UserRepository(apiService)
|
||||||
|
ProfileViewModel(userRepository)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
binding = ActivityDetailProfileBinding.inflate(layoutInflater)
|
||||||
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
sessionManager = SessionManager(this)
|
||||||
|
apiService = ApiConfig.getApiService(sessionManager)
|
||||||
|
|
||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
setContentView(R.layout.activity_detail_profile)
|
// ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
|
// val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||||
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
// v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
|
||||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
|
// insets
|
||||||
insets
|
// }
|
||||||
|
|
||||||
|
viewModel.loadUserProfile()
|
||||||
|
|
||||||
|
viewModel.userProfile.observe(this){ user ->
|
||||||
|
user?.let { updateProfile(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.errorMessage.observe(this) { error ->
|
||||||
|
Toast.makeText(this, error, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateProfile(user: UserProfile){
|
||||||
|
|
||||||
|
binding.tvNameUser.setText(user.name.toString())
|
||||||
|
binding.tvUsername.setText(user.username)
|
||||||
|
binding.tvEmailUser.setText(user.email)
|
||||||
|
binding.tvDateBirth.setText(formatDate(user.birthDate))
|
||||||
|
binding.tvNumberPhoneUser.setText(user.phone)
|
||||||
|
|
||||||
|
if (user.image != null && user.image is String) {
|
||||||
|
Glide.with(this)
|
||||||
|
.load(user.image)
|
||||||
|
.into(binding.profileImage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun formatDate(dateString: String): String {
|
||||||
|
return try {
|
||||||
|
val inputFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault()) //from json
|
||||||
|
inputFormat.timeZone = TimeZone.getTimeZone("UTC") //get timezone
|
||||||
|
val outputFormat = SimpleDateFormat("dd MMMM yyyy", Locale.getDefault()) // new format
|
||||||
|
val date = inputFormat.parse(dateString) // Parse from json format
|
||||||
|
outputFormat.format(date!!) // convert to new format
|
||||||
|
} catch (e: Exception) {
|
||||||
|
dateString // Return original if error occurs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,22 +1,43 @@
|
|||||||
package com.alya.ecommerce_serang.ui.profile
|
package com.alya.ecommerce_serang.ui.profile
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
|
import com.alya.ecommerce_serang.BuildConfig.BASE_URL
|
||||||
|
import com.alya.ecommerce_serang.R
|
||||||
|
import com.alya.ecommerce_serang.data.api.dto.UserProfile
|
||||||
|
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
|
||||||
|
import com.alya.ecommerce_serang.data.repository.UserRepository
|
||||||
import com.alya.ecommerce_serang.databinding.FragmentProfileBinding
|
import com.alya.ecommerce_serang.databinding.FragmentProfileBinding
|
||||||
|
import com.alya.ecommerce_serang.ui.profile.mystore.TokoSayaActivity
|
||||||
|
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
||||||
|
import com.alya.ecommerce_serang.utils.SessionManager
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
|
||||||
class ProfileFragment : Fragment() {
|
class ProfileFragment : Fragment() {
|
||||||
|
|
||||||
private var _binding: FragmentProfileBinding? = null
|
private var _binding: FragmentProfileBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
private lateinit var viewModel: ProfileViewModel
|
private lateinit var sessionManager: SessionManager
|
||||||
|
|
||||||
|
private val viewModel: ProfileViewModel by viewModels {
|
||||||
|
BaseViewModelFactory {
|
||||||
|
val apiService = ApiConfig.getApiService(sessionManager)
|
||||||
|
val userRepository = UserRepository(apiService)
|
||||||
|
ProfileViewModel(userRepository)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
sessionManager = SessionManager(requireContext())
|
||||||
|
|
||||||
// TODO: Use the ViewModel
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
@ -26,4 +47,49 @@ class ProfileFragment : Fragment() {
|
|||||||
_binding = FragmentProfileBinding.inflate(inflater, container, false)
|
_binding = FragmentProfileBinding.inflate(inflater, container, false)
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
observeUserProfile()
|
||||||
|
viewModel.loadUserProfile()
|
||||||
|
|
||||||
|
binding.cardBukaToko.setOnClickListener{
|
||||||
|
val intentBuka = Intent(requireContext(), TokoSayaActivity::class.java)
|
||||||
|
startActivity(intentBuka)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.btnDetailProfile.setOnClickListener{
|
||||||
|
val intentDetail = Intent(requireContext(), DetailProfileActivity::class.java)
|
||||||
|
startActivity(intentDetail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun observeUserProfile() {
|
||||||
|
viewModel.userProfile.observe(viewLifecycleOwner) { user ->
|
||||||
|
user?.let { updateUI(it) }
|
||||||
|
}
|
||||||
|
viewModel.errorMessage.observe(viewLifecycleOwner) { errorMessage ->
|
||||||
|
Toast.makeText(requireContext(), errorMessage, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateUI(user: UserProfile) = with(binding){
|
||||||
|
val fullImageUrl = when (val img = user.image) {
|
||||||
|
is String -> {
|
||||||
|
if (img.startsWith("/")) BASE_URL + img.substring(1) else img
|
||||||
|
}
|
||||||
|
else -> R.drawable.placeholder_image // Default image for null
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d("ProductAdapter", "Loading image: $fullImageUrl")
|
||||||
|
|
||||||
|
tvName.text = user.name.toString()
|
||||||
|
tvUsername.text = user.username.toString()
|
||||||
|
|
||||||
|
// Load image using Glide
|
||||||
|
Glide.with(requireContext())
|
||||||
|
.load(fullImageUrl)
|
||||||
|
.placeholder(R.drawable.placeholder_image)
|
||||||
|
.into(profileImage)
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,7 +1,28 @@
|
|||||||
package com.alya.ecommerce_serang.ui.profile
|
package com.alya.ecommerce_serang.ui.profile
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.alya.ecommerce_serang.data.api.dto.UserProfile
|
||||||
|
import com.alya.ecommerce_serang.data.repository.Result
|
||||||
|
import com.alya.ecommerce_serang.data.repository.UserRepository
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class ProfileViewModel : ViewModel() {
|
class ProfileViewModel(private val userRepository: UserRepository) : ViewModel() {
|
||||||
// TODO: Implement the ViewModel
|
private val _userProfile = MutableLiveData<UserProfile?>()
|
||||||
|
val userProfile: LiveData<UserProfile?> = _userProfile
|
||||||
|
|
||||||
|
private val _errorMessage = MutableLiveData<String>()
|
||||||
|
val errorMessage : LiveData<String> = _errorMessage
|
||||||
|
|
||||||
|
fun loadUserProfile(){
|
||||||
|
viewModelScope.launch {
|
||||||
|
when (val result = userRepository.fetchUserProfile()){
|
||||||
|
is Result.Success -> _userProfile.postValue(result.data)
|
||||||
|
is Result.Error -> _errorMessage.postValue(result.exception.message ?: "Unknown Error")
|
||||||
|
is Result.Loading -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -104,6 +104,7 @@
|
|||||||
app:layout_constraintTop_toBottomOf="@id/card_profile">
|
app:layout_constraintTop_toBottomOf="@id/card_profile">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/tv_name_user"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="Nama"
|
android:hint="Nama"
|
||||||
@ -120,6 +121,7 @@
|
|||||||
app:layout_constraintTop_toBottomOf="@id/til_nama">
|
app:layout_constraintTop_toBottomOf="@id/til_nama">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/tv_username"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="Username"
|
android:hint="Username"
|
||||||
@ -136,6 +138,7 @@
|
|||||||
app:layout_constraintTop_toBottomOf="@id/til_username">
|
app:layout_constraintTop_toBottomOf="@id/til_username">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/tv_email_user"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="Email"
|
android:hint="Email"
|
||||||
@ -152,6 +155,7 @@
|
|||||||
app:layout_constraintTop_toBottomOf="@id/til_email">
|
app:layout_constraintTop_toBottomOf="@id/til_email">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/tv_number_phone_user"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="Nomor Handphone"
|
android:hint="Nomor Handphone"
|
||||||
@ -168,6 +172,7 @@
|
|||||||
app:layout_constraintTop_toBottomOf="@id/til_nomor_handphone">
|
app:layout_constraintTop_toBottomOf="@id/til_nomor_handphone">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/tv_date_birth"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="Tanggal Lahir"
|
android:hint="Tanggal Lahir"
|
||||||
|
@ -45,6 +45,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:text="Detail Profil"
|
android:text="Detail Profil"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@id/profileImage" />
|
app:layout_constraintTop_toTopOf="@id/profileImage" />
|
||||||
|
|
||||||
@ -55,6 +57,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingHorizontal="16dp"
|
android:paddingHorizontal="16dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
app:cardElevation="4dp"
|
app:cardElevation="4dp"
|
||||||
app:layout_constraintTop_toBottomOf="@id/profileImage">
|
app:layout_constraintTop_toBottomOf="@id/profileImage">
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user