Merge branch 'screen-features'

This commit is contained in:
shaulascr
2025-06-12 21:48:13 +07:00
14 changed files with 56 additions and 63 deletions

View File

@ -5,19 +5,19 @@ import com.google.gson.annotations.SerializedName
data class DetailStoreProductResponse(
@field:SerializedName("shipping")
val shipping: List<ShippingItemDetail>,
val shipping: List<DetailShippingItem>,
@field:SerializedName("payment")
val payment: List<PaymentItemDetail>,
val payment: List<DetailPaymentItem>,
@field:SerializedName("store")
val store: StoreProduct,
val store: List<StoreItem>,
@field:SerializedName("message")
val message: String
)
data class StoreProduct(
data class StoreItem(
@field:SerializedName("store_id")
val storeId: Int,
@ -38,19 +38,19 @@ data class StoreProduct(
val storeLocation: String,
@field:SerializedName("store_image")
val storeImage: String? = null,
val storeImage: String,
@field:SerializedName("status")
val status: String
)
data class ShippingItemDetail(
data class DetailShippingItem(
@field:SerializedName("courier")
val courier: String
)
data class PaymentItemDetail(
data class DetailPaymentItem(
@field:SerializedName("qris_image")
val qrisImage: String,
@ -59,7 +59,7 @@ data class PaymentItemDetail(
val bankNum: String,
@field:SerializedName("account_name")
val accountName: Any,
val accountName: String,
@field:SerializedName("bank_name")
val bankName: String,

View File

@ -20,9 +20,9 @@ import com.alya.ecommerce_serang.data.api.response.customer.order.ListCityRespon
import com.alya.ecommerce_serang.data.api.response.customer.order.ListProvinceResponse
import com.alya.ecommerce_serang.data.api.response.customer.order.OrderDetailResponse
import com.alya.ecommerce_serang.data.api.response.customer.order.OrderListResponse
import com.alya.ecommerce_serang.data.api.response.customer.product.PaymentItemDetail
import com.alya.ecommerce_serang.data.api.response.customer.product.DetailPaymentItem
import com.alya.ecommerce_serang.data.api.response.customer.product.ProductResponse
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreProduct
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreItem
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreResponse
import com.alya.ecommerce_serang.data.api.response.customer.profile.AddressResponse
import com.alya.ecommerce_serang.data.api.response.customer.profile.CreateAddressResponse
@ -217,7 +217,7 @@ class OrderRepository(private val apiService: ApiService) {
}
}
suspend fun fetchStoreDetail(storeId: Int): Result<StoreProduct?> {
suspend fun fetchStoreDetail(storeId: Int): Result<List<StoreItem>> {
return try {
val response = apiService.getDetailStore(storeId)
if (response.isSuccessful) {
@ -238,7 +238,7 @@ class OrderRepository(private val apiService: ApiService) {
}
}
suspend fun fetchPaymentStore(storeId: Int): Result<List<PaymentItemDetail?>> {
suspend fun fetchPaymentStore(storeId: Int): Result<List<DetailPaymentItem?>> {
return try {
val response = apiService.getDetailStore(storeId)
if (response.isSuccessful) {

View File

@ -7,12 +7,12 @@ import com.alya.ecommerce_serang.data.api.dto.Preorder
import com.alya.ecommerce_serang.data.api.dto.ProductsItem
import com.alya.ecommerce_serang.data.api.dto.SearchRequest
import com.alya.ecommerce_serang.data.api.dto.Wholesale
import com.alya.ecommerce_serang.data.api.response.store.product.CreateProductResponse
import com.alya.ecommerce_serang.data.api.response.customer.cart.AddCartResponse
import com.alya.ecommerce_serang.data.api.response.customer.product.ProductResponse
import com.alya.ecommerce_serang.data.api.response.customer.product.ReviewsItem
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreProduct
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreItem
import com.alya.ecommerce_serang.data.api.response.product.Search
import com.alya.ecommerce_serang.data.api.response.store.product.CreateProductResponse
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@ -118,13 +118,13 @@ class ProductRepository(private val apiService: ApiService) {
}
}
suspend fun fetchStoreDetail(storeId: Int): Result<StoreProduct> {
suspend fun fetchStoreDetail(storeId: Int): Result<StoreItem> {
return try {
val response = apiService.getDetailStore(storeId)
if (response.isSuccessful) {
val store = response.body()?.store
if (store != null) {
Result.Success(store)
Result.Success(store[0])
} else {
Result.Error(Throwable("Empty response body"))
}

View File

@ -8,7 +8,7 @@ import androidx.lifecycle.viewModelScope
import com.alya.ecommerce_serang.data.api.response.chat.ChatItem
import com.alya.ecommerce_serang.data.api.response.chat.ChatItemList
import com.alya.ecommerce_serang.data.api.response.chat.ChatLine
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreProduct
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreItem
import com.alya.ecommerce_serang.data.repository.ChatRepository
import com.alya.ecommerce_serang.data.repository.Result
import com.alya.ecommerce_serang.utils.Constants
@ -44,8 +44,8 @@ class ChatViewModel @Inject constructor(
private val _chatListStore = MutableLiveData<Result<List<ChatItemList>>>()
val chatListStore: LiveData<Result<List<ChatItemList>>> = _chatListStore
private val _storeDetail = MutableLiveData<Result<StoreProduct?>>()
val storeDetail: LiveData<Result<StoreProduct?>> get() = _storeDetail
private val _storeDetail = MutableLiveData<Result<List<StoreItem?>>>()
val storeDetail: LiveData<Result<List<StoreItem?>>> get() = _storeDetail
// Chat parameters
private var storeId: Int = 0

View File

@ -66,7 +66,7 @@ class HorizontalProductAdapter(
fun updateLimitedProducts(newProducts: List<ProductsItem>) {
val diffCallback = ProductDiffCallback(products, newProducts)
val limitedProducts = newProducts.take(10) // Limit to 10 items
val limitedProducts = newProducts.take(10) //limit 10 produk
val diffResult = DiffUtil.calculateDiff(diffCallback)
diffResult.dispatchUpdatesTo(this)
updateProducts(limitedProducts)

View File

@ -19,7 +19,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.alya.ecommerce_serang.data.api.dto.CheckoutData
import com.alya.ecommerce_serang.data.api.dto.OrderRequest
import com.alya.ecommerce_serang.data.api.dto.OrderRequestBuy
import com.alya.ecommerce_serang.data.api.response.customer.product.PaymentItemDetail
import com.alya.ecommerce_serang.data.api.response.customer.product.DetailPaymentItem
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
import com.alya.ecommerce_serang.data.repository.OrderRepository
import com.alya.ecommerce_serang.databinding.ActivityCheckoutBinding
@ -185,7 +185,7 @@ class CheckoutActivity : AppCompatActivity() {
}
}
private fun setupPaymentMethodsRecyclerView(paymentMethods: List<PaymentItemDetail>) {
private fun setupPaymentMethodsRecyclerView(paymentMethods: List<DetailPaymentItem>) {
if (paymentMethods.isEmpty()) {
Log.e("CheckoutActivity", "Payment methods list is empty")
Toast.makeText(this, "No payment methods available", Toast.LENGTH_SHORT).show()
@ -210,7 +210,7 @@ class CheckoutActivity : AppCompatActivity() {
}
}
private fun updatePaymentMethodsAdapter(paymentMethods: List<PaymentItemDetail>, selectedId: Int?) {
private fun updatePaymentMethodsAdapter(paymentMethods: List<DetailPaymentItem>, selectedId: Int?) {
Log.d("CheckoutActivity", "Updating payment adapter with ${paymentMethods.size} methods")
// Simple test adapter

View File

@ -10,7 +10,7 @@ import com.alya.ecommerce_serang.data.api.dto.OrderRequest
import com.alya.ecommerce_serang.data.api.dto.OrderRequestBuy
import com.alya.ecommerce_serang.data.api.response.customer.cart.CartItemsItem
import com.alya.ecommerce_serang.data.api.response.customer.cart.DataItemCart
import com.alya.ecommerce_serang.data.api.response.customer.product.PaymentItemDetail
import com.alya.ecommerce_serang.data.api.response.customer.product.DetailPaymentItem
import com.alya.ecommerce_serang.data.api.response.customer.profile.AddressesItem
import com.alya.ecommerce_serang.data.repository.OrderRepository
import com.alya.ecommerce_serang.data.repository.Result
@ -24,12 +24,12 @@ class CheckoutViewModel(private val repository: OrderRepository) : ViewModel() {
private val _addressDetails = MutableLiveData<AddressesItem?>()
val addressDetails: LiveData<AddressesItem?> = _addressDetails
private val _availablePaymentMethods = MutableLiveData<List<PaymentItemDetail>>()
val availablePaymentMethods: LiveData<List<PaymentItemDetail>> = _availablePaymentMethods
private val _availablePaymentMethods = MutableLiveData<List<DetailPaymentItem>>()
val availablePaymentMethods: LiveData<List<DetailPaymentItem>> = _availablePaymentMethods
// Selected payment method
private val _selectedPayment = MutableLiveData<PaymentItemDetail?>()
val selectedPayment: LiveData<PaymentItemDetail?> = _selectedPayment
private val _selectedPayment = MutableLiveData<DetailPaymentItem?>()
val selectedPayment: LiveData<DetailPaymentItem?> = _selectedPayment
private val _isLoading = MutableLiveData<Boolean>()
val isLoading: LiveData<Boolean> = _isLoading

View File

@ -6,14 +6,14 @@ import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.data.api.response.customer.product.PaymentItemDetail
import com.alya.ecommerce_serang.data.api.response.customer.product.DetailPaymentItem
import com.alya.ecommerce_serang.databinding.ItemPaymentMethodBinding
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
class PaymentMethodAdapter(
private val paymentMethods: List<PaymentItemDetail>,
private val onPaymentSelected: (PaymentItemDetail) -> Unit
private val paymentMethods: List<DetailPaymentItem>,
private val onPaymentSelected: (DetailPaymentItem) -> Unit
) : RecyclerView.Adapter<PaymentMethodAdapter.PaymentMethodViewHolder>() {
// Track the selected payment by ID
@ -118,7 +118,7 @@ class PaymentMethodAdapter(
}
// Set selected payment object
fun setSelectedPayment(payment: PaymentItemDetail) {
fun setSelectedPayment(payment: DetailPaymentItem) {
setSelectedPaymentId(payment.id)
}
}

View File

@ -23,7 +23,7 @@ import com.alya.ecommerce_serang.data.api.dto.CartItem
import com.alya.ecommerce_serang.data.api.dto.ProductsItem
import com.alya.ecommerce_serang.data.api.response.customer.product.Product
import com.alya.ecommerce_serang.data.api.response.customer.product.ReviewsItem
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreProduct
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreItem
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
import com.alya.ecommerce_serang.data.repository.ProductRepository
@ -157,7 +157,7 @@ class DetailProductActivity : AppCompatActivity() {
}
}
private fun updateStoreInfo(store: StoreProduct?) {
private fun updateStoreInfo(store: StoreItem?) {
store?.let {
binding.tvSellerName.text = it.storeName
binding.tvSellerRating.text = it.storeRating

View File

@ -10,7 +10,7 @@ import com.alya.ecommerce_serang.data.api.dto.ProductsItem
import com.alya.ecommerce_serang.data.api.response.customer.cart.AddCartResponse
import com.alya.ecommerce_serang.data.api.response.customer.product.Product
import com.alya.ecommerce_serang.data.api.response.customer.product.ReviewsItem
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreProduct
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreItem
import com.alya.ecommerce_serang.data.repository.ProductRepository
import com.alya.ecommerce_serang.data.repository.Result
import kotlinx.coroutines.launch
@ -20,8 +20,8 @@ class ProductUserViewModel(private val repository: ProductRepository) : ViewMode
private val _productDetail = MutableLiveData<Product?>()
val productDetail: LiveData<Product?> get() = _productDetail
private val _storeDetail = MutableLiveData<Result<StoreProduct?>>()
val storeDetail : LiveData<Result<StoreProduct?>> get() = _storeDetail
private val _storeDetail = MutableLiveData<Result<StoreItem>>()
val storeDetail : LiveData<Result<StoreItem>> get() = _storeDetail
private val _reviewProduct = MutableLiveData<List<ReviewsItem>>()
val reviewProduct: LiveData<List<ReviewsItem>> get() = _reviewProduct
@ -51,7 +51,7 @@ class ProductUserViewModel(private val repository: ProductRepository) : ViewMode
loadStoreDetail(storeId)
}
} catch (e: Exception) {
Log.e("ProductViewModel", "Error loading product details: ${e.message}")
Log.e(TAG, "Error loading product details: ${e.message}")
_error.value = "Failed to load product details: ${e.message}"
} finally {
_isLoading.value = false
@ -64,9 +64,10 @@ class ProductUserViewModel(private val repository: ProductRepository) : ViewMode
try {
_storeDetail.value = Result.Loading
val result = repository.fetchStoreDetail(storeId)
Log.d(TAG, "Success call detail store: $result store id = $storeId")
_storeDetail.value = result
} catch (e: Exception) {
Log.e("ProductViewModel", "Error loading store details: ${e.message}")
Log.e(TAG, "Error loading store details: ${e.message}")
_storeDetail.value = Result.Error(e)
}
}
@ -78,7 +79,7 @@ class ProductUserViewModel(private val repository: ProductRepository) : ViewMode
val reviews = repository.fetchProductReview(productId)
_reviewProduct.value = reviews ?: emptyList()
} catch (e: Exception) {
Log.e("ProductViewModel", "Error loading reviews: ${e.message}")
Log.e(TAG, "Error loading reviews: ${e.message}")
_reviewProduct.value = emptyList()
}
}
@ -96,11 +97,11 @@ class ProductUserViewModel(private val repository: ProductRepository) : ViewMode
} // Filter by storeId and exclude current product
_otherProducts.value = filteredProducts // Update LiveData
} else if (result is Result.Error) {
Log.e("ProductViewModel", "Error loading other products: ${result.exception.message}")
Log.e(TAG, "Error loading other products: ${result.exception.message}")
_otherProducts.value = emptyList() // Set empty list on failure
}
} catch (e: Exception) {
Log.e("ProductViewModel", "Exception loading other products: ${e.message}")
Log.e(TAG, "Exception loading other products: ${e.message}")
_otherProducts.value = emptyList()
}
}
@ -125,6 +126,10 @@ class ProductUserViewModel(private val repository: ProductRepository) : ViewMode
}
}
companion object{
private var TAG = "ProductUserViewModel"
}
}
// fun loadStoreDetail(storeId: Int){

View File

@ -15,7 +15,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import com.alya.ecommerce_serang.BuildConfig.BASE_URL
import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.data.api.dto.ProductsItem
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreProduct
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreItem
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
import com.alya.ecommerce_serang.data.repository.ProductRepository
@ -117,7 +117,7 @@ class StoreDetailActivity : AppCompatActivity() {
viewModel.loadStoreDetail(storeId)
}
private fun updateStoreInfo(store: StoreProduct?) {
private fun updateStoreInfo(store: StoreItem?) {
store?.let {
binding.tvStoreName.text = it.storeName
binding.tvStoreRating.text = it.storeRating

View File

@ -7,7 +7,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.alya.ecommerce_serang.data.api.dto.ProductsItem
import com.alya.ecommerce_serang.data.api.response.customer.product.Product
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreProduct
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreItem
import com.alya.ecommerce_serang.data.repository.ProductRepository
import com.alya.ecommerce_serang.data.repository.Result
import kotlinx.coroutines.launch
@ -27,8 +27,8 @@ class StoreDetailViewModel (private val repository: ProductRepository
private val _error = MutableLiveData<String>()
val error: LiveData<String> get() = _error
private val _storeDetail = MutableLiveData<Result<StoreProduct>>()
val storeDetail : LiveData<Result<StoreProduct>> get() = _storeDetail
private val _storeDetail = MutableLiveData<Result<StoreItem>>()
val storeDetail : LiveData<Result<StoreItem>> get() = _storeDetail
fun loadOtherProducts(storeId: Int) {
viewModelScope.launch {

View File

@ -8,10 +8,10 @@ import com.alya.ecommerce_serang.data.api.dto.CategoryItem
import com.alya.ecommerce_serang.data.api.dto.Preorder
import com.alya.ecommerce_serang.data.api.dto.ProductsItem
import com.alya.ecommerce_serang.data.api.dto.Wholesale
import com.alya.ecommerce_serang.data.api.response.store.product.CreateProductResponse
import com.alya.ecommerce_serang.data.api.response.customer.product.Product
import com.alya.ecommerce_serang.data.api.response.customer.product.ReviewsItem
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreProduct
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreItem
import com.alya.ecommerce_serang.data.api.response.store.product.CreateProductResponse
import com.alya.ecommerce_serang.data.api.response.store.product.UpdateProductResponse
import com.alya.ecommerce_serang.data.repository.ProductRepository
import com.alya.ecommerce_serang.data.repository.Result
@ -30,8 +30,8 @@ class ProductViewModel(private val repository: ProductRepository) : ViewModel()
private val _productDetail = MutableLiveData<Product?>()
val productDetail: LiveData<Product?> get() = _productDetail
private val _storeDetail = MutableLiveData<StoreProduct?>()
val storeDetail : LiveData<StoreProduct?> get() = _storeDetail
private val _storeDetail = MutableLiveData<Result<StoreItem>>()
val storeDetail : LiveData<Result<StoreItem>> get() = _storeDetail
private val _reviewProduct = MutableLiveData<List<ReviewsItem>>()
val reviewProduct: LiveData<List<ReviewsItem>> get() = _reviewProduct

View File

@ -28,8 +28,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- Remove searchContainer from here, it's now at the top level -->
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/banners"
android:layout_width="match_parent"
@ -180,13 +178,3 @@
layout="@layout/view_error"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- <com.zhpan.indicator.IndicatorView-->
<!-- android:id="@+id/indicator"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginTop="20dp"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@+id/banners" />-->