From e8bb99a8d7aef8e8d52dc338fb316731bb722aba Mon Sep 17 00:00:00 2001 From: shaulascr Date: Thu, 10 Apr 2025 02:05:20 +0700 Subject: [PATCH] fix detail and address --- app/src/main/AndroidManifest.xml | 6 +- .../data/api/dto/OrderRequest.kt | 7 +- .../data/repository/OrderRepository.kt | 17 ++ .../data/repository/ProductRepository.kt | 18 ++ .../ui/order/ShippingActivity.kt | 106 ++++++++-- .../ui/order/ShippingAdapter.kt | 65 ++++++ .../ui/order/ShippingViewModel.kt | 33 +++ .../order/{ => address}/AddAddressActivity.kt | 2 +- .../{ => address}/AddAddressViewModel.kt | 21 +- .../ui/order/{ => address}/AddressActivity.kt | 12 +- .../ui/order/{ => address}/AddressAdapter.kt | 2 +- .../order/{ => address}/AddressViewModel.kt | 2 +- .../{ => address}/EditAddressActivity.kt | 2 +- .../ui/order/{ => address}/ProvinceAdapter.kt | 2 +- .../ui/product/DetailProductActivity.kt | 189 ++++++++++++++---- .../ui/product/ProductViewModel.kt | 96 +++++++-- .../main/res/layout/activity_add_address.xml | 2 +- app/src/main/res/layout/activity_address.xml | 2 +- .../main/res/layout/activity_edit_address.xml | 2 +- app/src/main/res/layout/activity_shipping.xml | 2 +- .../main/res/layout/item_shipping_order.xml | 36 +++- 21 files changed, 523 insertions(+), 101 deletions(-) create mode 100644 app/src/main/java/com/alya/ecommerce_serang/ui/order/ShippingAdapter.kt create mode 100644 app/src/main/java/com/alya/ecommerce_serang/ui/order/ShippingViewModel.kt rename app/src/main/java/com/alya/ecommerce_serang/ui/order/{ => address}/AddAddressActivity.kt (99%) rename app/src/main/java/com/alya/ecommerce_serang/ui/order/{ => address}/AddAddressViewModel.kt (73%) rename app/src/main/java/com/alya/ecommerce_serang/ui/order/{ => address}/AddressActivity.kt (85%) rename app/src/main/java/com/alya/ecommerce_serang/ui/order/{ => address}/AddressAdapter.kt (97%) rename app/src/main/java/com/alya/ecommerce_serang/ui/order/{ => address}/AddressViewModel.kt (94%) rename app/src/main/java/com/alya/ecommerce_serang/ui/order/{ => address}/EditAddressActivity.kt (93%) rename app/src/main/java/com/alya/ecommerce_serang/ui/order/{ => address}/ProvinceAdapter.kt (96%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4259d5c..6a4d648 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -20,13 +20,13 @@ android:usesCleartextTraffic="true" tools:targetApi="31"> , @SerializedName("ship_etd") val shipEtd: String diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/repository/OrderRepository.kt b/app/src/main/java/com/alya/ecommerce_serang/data/repository/OrderRepository.kt index 1932d38..5aa51a0 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/data/repository/OrderRepository.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/data/repository/OrderRepository.kt @@ -1,8 +1,10 @@ package com.alya.ecommerce_serang.data.repository import android.util.Log +import com.alya.ecommerce_serang.data.api.dto.CourierCostRequest import com.alya.ecommerce_serang.data.api.dto.CreateAddressRequest import com.alya.ecommerce_serang.data.api.dto.OrderRequest +import com.alya.ecommerce_serang.data.api.response.order.CourierCostResponse import com.alya.ecommerce_serang.data.api.response.order.CreateOrderResponse import com.alya.ecommerce_serang.data.api.response.order.ListCityResponse import com.alya.ecommerce_serang.data.api.response.order.ListProvinceResponse @@ -70,4 +72,19 @@ class OrderRepository(private val apiService: ApiService) { return if (response.isSuccessful) response.body() else null } + suspend fun getCountCourierCost(courierCost: CourierCostRequest): Result{ + return try { + val response = apiService.countCourierCost(courierCost) + if (response.isSuccessful){ + response.body()?.let { + Result.Success(it) + } ?: Result.Error(Exception("Add Address failed")) + } else { + Log.e("OrderRepository", "Error: ${response.errorBody()?.string()}") + Result.Error(Exception(response.errorBody()?.string() ?: "Unknown error")) + } + } catch (e: Exception) { + Result.Error(e) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/repository/ProductRepository.kt b/app/src/main/java/com/alya/ecommerce_serang/data/repository/ProductRepository.kt index 2917c39..43da21b 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/data/repository/ProductRepository.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/data/repository/ProductRepository.kt @@ -1,8 +1,10 @@ package com.alya.ecommerce_serang.data.repository import android.util.Log +import com.alya.ecommerce_serang.data.api.dto.CartItem import com.alya.ecommerce_serang.data.api.dto.CategoryItem import com.alya.ecommerce_serang.data.api.dto.ProductsItem +import com.alya.ecommerce_serang.data.api.response.cart.AddCartResponse import com.alya.ecommerce_serang.data.api.response.product.ProductResponse import com.alya.ecommerce_serang.data.api.response.product.ReviewsItem import com.alya.ecommerce_serang.data.api.retrofit.ApiService @@ -79,6 +81,22 @@ class ProductRepository(private val apiService: ApiService) { null } } + + suspend fun addToCart(request: CartItem): Result { + return try{ + val response = apiService.addCart(request) + if (response.isSuccessful){ + response.body()?.let { + Result.Success(it) + } ?: Result.Error(Exception("Add Cart failed")) + } else { + Log.e("OrderRepository", "Error: ${response.errorBody()?.string()}") + Result.Error(Exception(response.errorBody()?.string() ?: "Unknown Error")) + } + } catch (e: Exception){ + Result.Error(e) + } + } } // suspend fun fetchStoreDetail(storeId: Int): Store? { diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/ShippingActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/ShippingActivity.kt index b9441c6..c462215 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/ShippingActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/ShippingActivity.kt @@ -1,21 +1,103 @@ package com.alya.ecommerce_serang.ui.order +import android.content.Intent import android.os.Bundle -import androidx.activity.enableEdgeToEdge +import android.widget.Toast +import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat +import androidx.lifecycle.lifecycleScope +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import com.alya.ecommerce_serang.R +import com.alya.ecommerce_serang.data.api.dto.CostProduct +import com.alya.ecommerce_serang.data.api.dto.CourierCostRequest +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.OrderRepository +import com.alya.ecommerce_serang.data.repository.Result +import com.alya.ecommerce_serang.databinding.ActivityCheckoutBinding +import com.alya.ecommerce_serang.utils.BaseViewModelFactory +import com.alya.ecommerce_serang.utils.SessionManager +import com.google.android.material.appbar.MaterialToolbar +import kotlinx.coroutines.launch class ShippingActivity : AppCompatActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContentView(R.layout.activity_shipping) - ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> - val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) - v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) - insets + private lateinit var binding: ActivityCheckoutBinding + private lateinit var apiService: ApiService + private lateinit var sessionManager: SessionManager + private lateinit var adapter: ShippingAdapter + + private val viewModel: ShippingViewModel by viewModels { + BaseViewModelFactory { + val apiService = ApiConfig.getApiService(sessionManager) + val orderRepository = OrderRepository(apiService) + ShippingViewModel(orderRepository) } } -} \ No newline at end of file + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityCheckoutBinding.inflate(layoutInflater) + setContentView(binding.root) + + sessionManager = SessionManager(this) + apiService = ApiConfig.getApiService(sessionManager) + + val recyclerView = findViewById(R.id.rv_shipment_order) + adapter = ShippingAdapter { selectedService -> + val intent = Intent().apply { + putExtra("ship_name", selectedService.service) + putExtra("ship_price", selectedService.cost) + putExtra("ship_service", selectedService.description) + } + setResult(RESULT_OK, intent) + finish() + } + recyclerView.adapter = adapter + recyclerView.layoutManager = LinearLayoutManager(this) + + val request = CourierCostRequest( + addressId = intent.getIntExtra("extra_address_id", 0), + itemCost = CostProduct( + productId = intent.getIntExtra("product_id", 0), + quantity = intent.getIntExtra("quantity", 1) + ) + ) + + viewModel.fetchShippingServices(request) + + lifecycleScope.launch { + viewModel.shippingServices.collect { result -> + result?.let { + when (it) { + is Result.Success -> adapter.submitList(it.data) + is Result.Error -> Toast.makeText(this@ShippingActivity, it.exception.message, Toast.LENGTH_SHORT).show() + is Result.Loading -> null + } + } + } + } + + findViewById(R.id.toolbar).setNavigationOnClickListener { + finish() + } + } +} + +//val launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> +// if (result.resultCode == RESULT_OK) { +// val data = result.data +// val shipName = data?.getStringExtra("ship_name") +// val shipPrice = data?.getIntExtra("ship_price", 0) +// val shipService = data?.getStringExtra("ship_service") +// // use the data as needed +// } +//} +// +//// launch the shipping activity +//val intent = Intent(this, ShippingActivity::class.java).apply { +// putExtra("address_id", addressId) +// putExtra("product_id", productId) +// putExtra("quantity", quantity) +//} +//launcher.launch(intent) diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/ShippingAdapter.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/ShippingAdapter.kt new file mode 100644 index 0000000..abc086d --- /dev/null +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/ShippingAdapter.kt @@ -0,0 +1,65 @@ +package com.alya.ecommerce_serang.ui.order + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.RadioButton +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.alya.ecommerce_serang.R +import com.alya.ecommerce_serang.data.api.response.order.ServicesItem + +class ShippingAdapter( + private val onItemSelected: (ServicesItem) -> Unit +) : RecyclerView.Adapter() { + + private var services = listOf() + private var selectedPosition = -1 + + fun submitList(newList: List) { + services = newList + notifyDataSetChanged() + } + + inner class ShippingViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + private val courierName = itemView.findViewById(R.id.courier_name_cost) + private val estDate = itemView.findViewById(R.id.est_date) + private val costPrice = itemView.findViewById(R.id.cost_price) + private val radioButton = itemView.findViewById(R.id.radio_btn_cost) + + fun bind(service: ServicesItem, isSelected: Boolean) { + courierName.text = service.service // already includes courier name from ViewModel + estDate.text = "Estimasi ${service.etd}" + costPrice.text = "Rp${service.cost}" + radioButton.isChecked = isSelected + + itemView.setOnClickListener { + if (adapterPosition != RecyclerView.NO_POSITION) { + selectedPosition = adapterPosition + notifyDataSetChanged() + onItemSelected(service) + } + } + + radioButton.setOnClickListener { + if (adapterPosition != RecyclerView.NO_POSITION) { + selectedPosition = adapterPosition + notifyDataSetChanged() + onItemSelected(service) + } + } + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ShippingViewHolder { + val view = LayoutInflater.from(parent.context).inflate(R.layout.item_shipping_order, parent, false) + return ShippingViewHolder(view) + } + + override fun onBindViewHolder(holder: ShippingViewHolder, position: Int) { + val service = services[position] + holder.bind(service, position == selectedPosition) + } + + override fun getItemCount(): Int = services.size +} diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/ShippingViewModel.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/ShippingViewModel.kt new file mode 100644 index 0000000..1fc08c8 --- /dev/null +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/ShippingViewModel.kt @@ -0,0 +1,33 @@ +package com.alya.ecommerce_serang.ui.order + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.alya.ecommerce_serang.data.api.dto.CourierCostRequest +import com.alya.ecommerce_serang.data.api.response.order.ServicesItem +import com.alya.ecommerce_serang.data.repository.OrderRepository +import com.alya.ecommerce_serang.data.repository.Result +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch + +class ShippingViewModel(private val repository: OrderRepository): ViewModel() { + + private val _shippingServices = MutableStateFlow>?>(null) + val shippingServices: StateFlow>?> = _shippingServices + + fun fetchShippingServices(request: CourierCostRequest) { + viewModelScope.launch { + val result = repository.getCountCourierCost(request) + if (result is Result.Success) { + val services = result.data.courierCosts.flatMap { courier -> + courier.services.map { + it.copy(service = "${courier.courier} - ${it.service}") + } + } + _shippingServices.value = Result.Success(services) + } else if (result is Result.Error) { + _shippingServices.value = Result.Error(result.exception) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/AddAddressActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressActivity.kt similarity index 99% rename from app/src/main/java/com/alya/ecommerce_serang/ui/order/AddAddressActivity.kt rename to app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressActivity.kt index 69e72db..c4b3587 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/AddAddressActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressActivity.kt @@ -1,4 +1,4 @@ -package com.alya.ecommerce_serang.ui.order +package com.alya.ecommerce_serang.ui.order.address import android.annotation.SuppressLint import android.content.pm.PackageManager diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/AddAddressViewModel.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressViewModel.kt similarity index 73% rename from app/src/main/java/com/alya/ecommerce_serang/ui/order/AddAddressViewModel.kt rename to app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressViewModel.kt index 0f1e09c..acf82b2 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/AddAddressViewModel.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressViewModel.kt @@ -1,4 +1,4 @@ -package com.alya.ecommerce_serang.ui.order +package com.alya.ecommerce_serang.ui.order.address import android.util.Log import androidx.lifecycle.SavedStateHandle @@ -15,13 +15,13 @@ import kotlinx.coroutines.launch class AddAddressViewModel(private val repository: OrderRepository, private val savedStateHandle: SavedStateHandle): ViewModel() { // Flow states for data - private val _addressSubmissionState = MutableStateFlow>(com.alya.ecommerce_serang.ui.order.ViewState.Loading) + private val _addressSubmissionState = MutableStateFlow>(ViewState.Loading) val addressSubmissionState = _addressSubmissionState.asStateFlow() - private val _provincesState = MutableStateFlow>>(com.alya.ecommerce_serang.ui.order.ViewState.Loading) + private val _provincesState = MutableStateFlow>>(ViewState.Loading) val provincesState = _provincesState.asStateFlow() - private val _citiesState = MutableStateFlow>>(com.alya.ecommerce_serang.ui.order.ViewState.Loading) + private val _citiesState = MutableStateFlow>>(ViewState.Loading) val citiesState = _citiesState.asStateFlow() // Stored in SavedStateHandle for configuration changes @@ -46,7 +46,8 @@ class AddAddressViewModel(private val repository: OrderRepository, private val s _addressSubmissionState.value = ViewState.Success(message) } is Result.Error -> { - _addressSubmissionState.value = ViewState.Error(result.exception.message ?: "Unknown error") + _addressSubmissionState.value = + ViewState.Error(result.exception.message ?: "Unknown error") } is Result.Loading -> { // Optional, karena sudah set Loading di awal @@ -60,7 +61,7 @@ class AddAddressViewModel(private val repository: OrderRepository, private val s try { val result = repository.getListProvinces() result?.let { - _provincesState.value = com.alya.ecommerce_serang.ui.order.ViewState.Success(it.provinces) + _provincesState.value = ViewState.Success(it.provinces) } } catch (e: Exception) { Log.e("AddAddressViewModel", "Error fetching provinces: ${e.message}") @@ -74,7 +75,7 @@ class AddAddressViewModel(private val repository: OrderRepository, private val s selectedProvinceId = provinceId val result = repository.getListCities(provinceId) result?.let { - _citiesState.value = com.alya.ecommerce_serang.ui.order.ViewState.Success(it.cities) + _citiesState.value = ViewState.Success(it.cities) } } catch (e: Exception) { Log.e("AddAddressViewModel", "Error fetching cities: ${e.message}") @@ -99,7 +100,7 @@ class AddAddressViewModel(private val repository: OrderRepository, private val s } sealed class ViewState { - object Loading : com.alya.ecommerce_serang.ui.order.ViewState() - data class Success(val data: T) : com.alya.ecommerce_serang.ui.order.ViewState() - data class Error(val message: String) : com.alya.ecommerce_serang.ui.order.ViewState() + object Loading : ViewState() + data class Success(val data: T) : ViewState() + data class Error(val message: String) : ViewState() } \ No newline at end of file diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/AddressActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddressActivity.kt similarity index 85% rename from app/src/main/java/com/alya/ecommerce_serang/ui/order/AddressActivity.kt rename to app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddressActivity.kt index bbc5e0c..0311d0e 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/AddressActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddressActivity.kt @@ -1,4 +1,4 @@ -package com.alya.ecommerce_serang.ui.order +package com.alya.ecommerce_serang.ui.order.address import android.content.Intent import android.os.Bundle @@ -64,4 +64,12 @@ class AddressActivity : AppCompatActivity() { } finish() } -} \ No newline at end of file +} + +//override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { +// super.onActivityResult(requestCode, resultCode, data) +// if (requestCode == REQUEST_ADDRESS && resultCode == RESULT_OK) { +// val selectedAddressId = data?.getIntExtra("selected_address_id", -1) +// // Use the selected address ID +// } +//} diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/AddressAdapter.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddressAdapter.kt similarity index 97% rename from app/src/main/java/com/alya/ecommerce_serang/ui/order/AddressAdapter.kt rename to app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddressAdapter.kt index e6a7e82..297a3e7 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/AddressAdapter.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddressAdapter.kt @@ -1,4 +1,4 @@ -package com.alya.ecommerce_serang.ui.order +package com.alya.ecommerce_serang.ui.order.address import android.view.LayoutInflater import android.view.View diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/AddressViewModel.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddressViewModel.kt similarity index 94% rename from app/src/main/java/com/alya/ecommerce_serang/ui/order/AddressViewModel.kt rename to app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddressViewModel.kt index 6bbcb8e..0898e2f 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/AddressViewModel.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddressViewModel.kt @@ -1,4 +1,4 @@ -package com.alya.ecommerce_serang.ui.order +package com.alya.ecommerce_serang.ui.order.address import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/EditAddressActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/EditAddressActivity.kt similarity index 93% rename from app/src/main/java/com/alya/ecommerce_serang/ui/order/EditAddressActivity.kt rename to app/src/main/java/com/alya/ecommerce_serang/ui/order/address/EditAddressActivity.kt index 6ae6a61..574a7a8 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/EditAddressActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/EditAddressActivity.kt @@ -1,4 +1,4 @@ -package com.alya.ecommerce_serang.ui.order +package com.alya.ecommerce_serang.ui.order.address import android.os.Bundle import androidx.activity.enableEdgeToEdge diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/ProvinceAdapter.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/ProvinceAdapter.kt similarity index 96% rename from app/src/main/java/com/alya/ecommerce_serang/ui/order/ProvinceAdapter.kt rename to app/src/main/java/com/alya/ecommerce_serang/ui/order/address/ProvinceAdapter.kt index 5af133a..44f7c29 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/ProvinceAdapter.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/ProvinceAdapter.kt @@ -1,4 +1,4 @@ -package com.alya.ecommerce_serang.ui.order +package com.alya.ecommerce_serang.ui.order.address import android.content.Context import android.widget.ArrayAdapter diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/product/DetailProductActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/product/DetailProductActivity.kt index 4857cb9..8242847 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/product/DetailProductActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/product/DetailProductActivity.kt @@ -3,20 +3,25 @@ package com.alya.ecommerce_serang.ui.product import android.content.Intent import android.os.Bundle import android.util.Log +import android.view.View import android.widget.Button import android.widget.ImageButton import android.widget.TextView +import android.widget.Toast import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity 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.CartItem import com.alya.ecommerce_serang.data.api.dto.ProductsItem import com.alya.ecommerce_serang.data.api.response.product.Product import com.alya.ecommerce_serang.data.api.response.product.ReviewsItem +import com.alya.ecommerce_serang.data.api.response.product.StoreProduct 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 +import com.alya.ecommerce_serang.data.repository.Result import com.alya.ecommerce_serang.databinding.ActivityDetailProductBinding import com.alya.ecommerce_serang.ui.home.HorizontalProductAdapter import com.alya.ecommerce_serang.ui.order.CheckoutActivity @@ -31,6 +36,8 @@ class DetailProductActivity : AppCompatActivity() { private lateinit var sessionManager: SessionManager private var productAdapter: HorizontalProductAdapter? = null private var reviewsAdapter: ReviewsAdapter? = null + private var currentQuantity = 1 + private val viewModel: ProductViewModel by viewModels { BaseViewModelFactory { @@ -47,43 +54,125 @@ class DetailProductActivity : AppCompatActivity() { sessionManager = SessionManager(this) apiService = ApiConfig.getApiService(sessionManager) +// val productId = intent.getIntExtra("PRODUCT_ID", -1) +// //nanti tambah get store id dari HomeFragment Product.storeId +// if (productId == -1) { +// Log.e("DetailProductActivity", "Invalid Product ID") +// finish() // Close activity if no valid ID +// return +// } + + setupUI() + setupObservers() + loadData() + } + + private fun loadData() { val productId = intent.getIntExtra("PRODUCT_ID", -1) - //nanti tambah get store id dari HomeFragment Product.storeId if (productId == -1) { Log.e("DetailProductActivity", "Invalid Product ID") + Toast.makeText(this, "Invalid product ID", Toast.LENGTH_SHORT).show() finish() // Close activity if no valid ID return } viewModel.loadProductDetail(productId) viewModel.loadReviews(productId) - - observeProductDetail() - observeProductReviews() } - private fun observeProductDetail() { + private fun setupObservers() { viewModel.productDetail.observe(this) { product -> product?.let { updateUI(it) viewModel.loadOtherProducts(it.storeId) } } + + viewModel.storeDetail.observe(this) { store -> + updateStoreInfo(store) + } + viewModel.otherProducts.observe(this) { products -> updateOtherProducts(products) } - } - private fun observeProductReviews() { viewModel.reviewProduct.observe(this) { reviews -> setupRecyclerViewReviewsProduct(reviews) } +// +// viewModel.isLoading.observe(this) { isLoading -> +// binding.progressBar.visibility = if (isLoading) View.VISIBLE else View.GONE +// } +// +// viewModel.error.observe(this) { errorMessage -> +// if (errorMessage.isNotEmpty()) { +// Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show() +// } +// } + + viewModel.addCart.observe(this) { result -> + when (result) { + is com.alya.ecommerce_serang.data.repository.Result.Success -> { + Toast.makeText(this, result.data, Toast.LENGTH_SHORT).show() + + // Check if we need to navigate to checkout (for "Buy Now" flow) + if (viewModel.shouldNavigateToCheckout) { + viewModel.shouldNavigateToCheckout = false + navigateToCheckout() + } + } + is com.alya.ecommerce_serang.data.repository.Result.Error -> { + Toast.makeText(this, "Failed to add to cart: ${result.exception.message}", Toast.LENGTH_SHORT).show() + } + is Result.Loading -> { + // Show loading indicator if needed + } + } + } + } + + private fun updateStoreInfo(store: StoreProduct?) { + store?.let { + binding.tvSellerName.text = it.storeName + // Add more store details as needed + } } private fun updateOtherProducts(products: List) { - productAdapter?.updateProducts(products) // Make sure your adapter has a method to update data - } + if (products.isEmpty()) { + binding.recyclerViewOtherProducts.visibility = View.GONE + binding.tvViewAllProducts.visibility = View.GONE + } else { + binding.recyclerViewOtherProducts.visibility = View.VISIBLE + binding.tvViewAllProducts.visibility = View.VISIBLE + productAdapter?.updateProducts(products) + } } + private fun setupUI() { +// binding.btnBack.setOnClickListener { +// finish() +// } + + binding.tvViewAllReviews.setOnClickListener { + viewModel.productDetail.value?.productId?.let { productId -> + handleAllReviewsClick(productId) + } + } + + binding.btnBuyNow.setOnClickListener { + viewModel.productDetail.value?.productId?.let { id -> + showBuyNowPopup(id) + } + } + + binding.btnAddToCart.setOnClickListener { + viewModel.productDetail.value?.productId?.let { id -> + showAddToCartPopup(id) + } + } + + setupRecyclerViewOtherProducts() + } private fun updateUI(product: Product){ binding.tvProductName.text = product.productName @@ -96,16 +185,6 @@ class DetailProductActivity : AppCompatActivity() { binding.tvDescription.text = product.description binding.tvSellerName.text = product.storeId.toString() - binding.tvViewAllReviews.setOnClickListener{ - handleAllReviewsClick(product.productId) - } - - binding.btnBuyNow.setOnClickListener { - viewModel.productDetail.value?.productId?.let { id -> - showBuyNowPopup(id) - } - } - val fullImageUrl = when (val img = product.image) { is String -> { @@ -119,8 +198,6 @@ class DetailProductActivity : AppCompatActivity() { .load(fullImageUrl) .placeholder(R.drawable.placeholder_image) .into(binding.ivProductImage) - - setupRecyclerViewOtherProducts() } private fun handleAllReviewsClick(productId: Int) { @@ -132,7 +209,7 @@ class DetailProductActivity : AppCompatActivity() { private fun setupRecyclerViewOtherProducts(){ productAdapter = HorizontalProductAdapter( products = emptyList(), - onClick = { productsItem -> handleProductClick(productsItem) } + onClick = { productsItem -> handleProductClick(productsItem) } ) binding.recyclerViewOtherProducts.apply { @@ -147,7 +224,15 @@ class DetailProductActivity : AppCompatActivity() { private fun setupRecyclerViewReviewsProduct(reviewList: List){ val limitedReviewList = if (reviewList.isNotEmpty()) listOf(reviewList.first()) else emptyList() - + if (reviewList.isEmpty()) { + binding.recyclerViewReviews.visibility = View.GONE + binding.tvViewAllReviews.visibility = View.GONE +// binding.tvNoReviews.visibility = View.VISIBLE + } else { + binding.recyclerViewReviews.visibility = View.VISIBLE + binding.tvViewAllReviews.visibility = View.VISIBLE + } +// binding.tvNoReviews.visibility = View.GONE reviewsAdapter = ReviewsAdapter( reviewList = limitedReviewList ) @@ -169,6 +254,14 @@ class DetailProductActivity : AppCompatActivity() { } private fun showBuyNowPopup(productId: Int) { + showQuantityDialog(productId, true) + } + + private fun showAddToCartPopup(productId: Int) { + showQuantityDialog(productId, false) + } + + private fun showQuantityDialog(productId: Int, isBuyNow: Boolean) { val bottomSheetDialog = BottomSheetDialog(this) val view = layoutInflater.inflate(R.layout.dialog_count_buy, null) bottomSheetDialog.setContentView(view) @@ -179,33 +272,59 @@ class DetailProductActivity : AppCompatActivity() { val btnBuyNow = view.findViewById