diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/home/HomeCategoryAdapter.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/home/HomeCategoryAdapter.kt index 5bdc7dc..9a8a788 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/home/HomeCategoryAdapter.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/home/HomeCategoryAdapter.kt @@ -12,7 +12,6 @@ import com.bumptech.glide.Glide class HomeCategoryAdapter( private var categories:List, - //A lambda function that will be invoked when a category item is clicked. private val onClick:(category:CategoryItem) -> Unit ): RecyclerView.Adapter() { diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/home/HomeFragment.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/home/HomeFragment.kt index 2c6cc9d..0965a96 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/home/HomeFragment.kt @@ -15,7 +15,7 @@ import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import androidx.navigation.findNavController import androidx.recyclerview.widget.GridLayoutManager -import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView 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.customer.product.StoreItem @@ -83,20 +83,15 @@ class HomeFragment : Fragment() { binding.newProducts.apply { adapter = productAdapter - layoutManager = GridLayoutManager( - context, - 2, - LinearLayoutManager.HORIZONTAL, - false - ) + layoutManager = GridLayoutManager(requireContext(), 2) } binding.categories.apply { adapter = categoryAdapter layoutManager = GridLayoutManager( context, - 3, - LinearLayoutManager.HORIZONTAL, + 3, // 3 columns + RecyclerView.VERTICAL, // vertical layout false ) } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/HistoryViewModel.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/HistoryViewModel.kt index c2df487..1a6f8e5 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/HistoryViewModel.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/HistoryViewModel.kt @@ -91,7 +91,7 @@ class HistoryViewModel(private val repository: OrderRepository) : ViewModel() { private suspend fun getAllOrdersCombined() { try { - val allStatuses = listOf("pending", "unpaid", "processed", "shipped", "completed", "canceled") + val allStatuses = listOf("unpaid", "paid", "processed", "shipped", "completed", "canceled") val allOrders = mutableListOf() // Use coroutineScope to allow launching async blocks @@ -211,10 +211,7 @@ class HistoryViewModel(private val repository: OrderRepository) : ViewModel() { fun refreshOrders(status: String = "all") { Log.d(TAG, "Refreshing orders with status: $status") - // Clear current orders before fetching new ones - _orders.value = ViewState.Loading - - // Re-fetch the orders with the current status + // Don't set Loading here if you want to show current data while refreshing getOrderList(status) } } \ No newline at end of file diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryAdapter.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryAdapter.kt index a67a2d7..f395ec2 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryAdapter.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryAdapter.kt @@ -4,7 +4,6 @@ import android.app.Activity import android.app.Dialog import android.content.ContextWrapper import android.content.Intent -import android.graphics.Color import android.net.Uri import android.provider.MediaStore import android.util.Log @@ -15,10 +14,10 @@ import android.view.Window import android.widget.ArrayAdapter import android.widget.AutoCompleteTextView import android.widget.ImageView -import android.widget.ProgressBar import android.widget.TextView import android.widget.Toast import androidx.fragment.app.FragmentActivity +import androidx.lifecycle.Observer import androidx.lifecycle.findViewTreeLifecycleOwner import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -40,9 +39,16 @@ import java.util.TimeZone class OrderHistoryAdapter( private val onOrderClickListener: (OrdersItem) -> Unit, - private val viewModel: HistoryViewModel // Add this parameter + private val viewModel: HistoryViewModel, + private val callbacks: OrderActionCallbacks ) : RecyclerView.Adapter() { + interface OrderActionCallbacks { + fun onOrderCancelled(orderId: String, success: Boolean, message: String) + fun onOrderCompleted(orderId: Int, success: Boolean, message: String) + fun onShowLoading(show: Boolean) + } + private val orders = mutableListOf() private var fragmentStatus: String = "all" @@ -140,28 +146,6 @@ class OrderHistoryAdapter( deadlineLabel.visibility = View.GONE when (status) { - "pending" -> { - statusOrder.apply { - visibility = View.VISIBLE - text = itemView.context.getString(R.string.pending_orders) - } - deadlineLabel.apply { - visibility = View.VISIBLE - text = itemView.context.getString(R.string.dl_pending) - } - btnLeft.apply { - visibility = View.VISIBLE - text = itemView.context.getString(R.string.canceled_order_btn) - setOnClickListener { - showCancelOrderBottomSheet(order.orderId) - viewModel.refreshOrders() - } - } - deadlineDate.apply { - visibility = View.VISIBLE - text = formatDate(order.createdAt) - } - } "unpaid" -> { statusOrder.apply { visibility = View.VISIBLE @@ -176,7 +160,6 @@ class OrderHistoryAdapter( text = itemView.context.getString(R.string.canceled_order_btn) setOnClickListener { showCancelOrderBottomSheet(order.orderId) - viewModel.refreshOrders() } } @@ -198,6 +181,28 @@ class OrderHistoryAdapter( text = formatDatePay(order.updatedAt) } } + "paid" -> { + statusOrder.apply { + visibility = View.VISIBLE + text = itemView.context.getString(R.string.paid_orders) + } + deadlineLabel.apply { + visibility = View.VISIBLE + text = itemView.context.getString(R.string.dl_paid) + } + btnLeft.apply { + visibility = View.VISIBLE + text = itemView.context.getString(R.string.canceled_order_btn) + setOnClickListener { + showCancelOrderDialog(order.orderId.toString()) + viewModel.refreshOrders() + } + } +// deadlineDate.apply { +// visibility = View.VISIBLE +// text = formatDatePay(order.updatedAt) +// } + } "processed" -> { // Untuk status processed, tampilkan "Hubungi Penjual" statusOrder.apply { @@ -239,11 +244,14 @@ class OrderHistoryAdapter( visibility = View.VISIBLE text = itemView.context.getString(R.string.claim_order) setOnClickListener { - // Handle click event + callbacks.onShowLoading(true) + + // Call ViewModel viewModel.confirmOrderCompleted(order.orderId, "completed") viewModel.refreshOrders() } + } deadlineDate.apply { visibility = View.VISIBLE @@ -454,52 +462,32 @@ class OrderHistoryAdapter( } } - // Show loading indicator - val loadingView = View(context).apply { - layoutParams = ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT - ) - setBackgroundColor(Color.parseColor("#80000000")) + callbacks.onShowLoading(true) - val progressBar = ProgressBar(context).apply { - layoutParams = ViewGroup.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ) - } - -// addView(progressBar) -// (progressBar.layoutParams as? ViewGroup.MarginLayoutParams)?.apply { -// gravity = Gravity.CENTER -// } - } - - dialog.addContentView(loadingView, loadingView.layoutParams) - - // Call the ViewModel to cancel the order with image + // Call ViewModel method but don't observe here viewModel.cancelOrderWithImage(orderId, reason, imageFile) - // Observe for success/failure - viewModel.isSuccess.observe(itemView.findViewTreeLifecycleOwner()!!) { isSuccess -> - // Remove loading indicator - (loadingView.parent as? ViewGroup)?.removeView(loadingView) + // Create a one-time observer that will be removed automatically + val observer = object : Observer { + override fun onChanged(isSuccess: Boolean) { + callbacks.onShowLoading(false) - if (isSuccess) { - Toast.makeText(context, context.getString(R.string.order_canceled_successfully), Toast.LENGTH_SHORT).show() - dialog.dismiss() - - // Find the order in the list and remove it or update its status - val position = orders.indexOfFirst { it.orderId.toString() == orderId } - if (position != -1) { - orders.removeAt(position) - notifyItemRemoved(position) - notifyItemRangeChanged(position, orders.size) + if (isSuccess) { + val message = viewModel.message.value ?: context.getString(R.string.order_canceled_successfully) + callbacks.onOrderCancelled(orderId, true, message) + dialog.dismiss() + } else { + val message = viewModel.message.value ?: context.getString(R.string.failed_to_cancel_order) + callbacks.onOrderCancelled(orderId, false, message) } - } else { - Toast.makeText(context, viewModel.message.value ?: context.getString(R.string.failed_to_cancel_order), Toast.LENGTH_SHORT).show() + + // Remove this observer after first use + viewModel.isSuccess.removeObserver(this) } } + + // Add observer only once + viewModel.isSuccess.observe(itemView.findViewTreeLifecycleOwner()!!, observer) } dialog.show() } @@ -534,10 +522,7 @@ class OrderHistoryAdapter( val bottomSheet = CancelOrderBottomSheet( orderId = orderId, onOrderCancelled = { - // Handle the successful cancellation - // Refresh the data - viewModel.refreshOrders() // Assuming there's a method to refresh orders - + callbacks.onOrderCancelled(orderId.toString(), true, "Order cancelled successfully") // Show a success message Toast.makeText(context, "Order cancelled successfully", Toast.LENGTH_SHORT).show() } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryFragment.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryFragment.kt index 267eb28..353a952 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryFragment.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryFragment.kt @@ -44,8 +44,8 @@ class OrderHistoryFragment : Fragment() { TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position -> tab.text = when (position) { 0 -> getString(R.string.all_orders) - 1 -> getString(R.string.pending_orders) - 2 -> getString(R.string.unpaid_orders) + 1 -> getString(R.string.unpaid_orders) + 2 -> getString(R.string.paid_orders) 3 -> getString(R.string.processed_orders) 4 -> getString(R.string.shipped_orders) 5 -> getString(R.string.completed_orders) diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderListFragment.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderListFragment.kt index 5e43898..28931bd 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderListFragment.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderListFragment.kt @@ -21,7 +21,7 @@ import com.alya.ecommerce_serang.ui.order.history.detailorder.DetailOrderStatusA import com.alya.ecommerce_serang.utils.BaseViewModelFactory import com.alya.ecommerce_serang.utils.SessionManager -class OrderListFragment : Fragment() { +class OrderListFragment : Fragment(), OrderHistoryAdapter.OrderActionCallbacks { private var _binding: FragmentOrderListBinding? = null private val binding get() = _binding!! @@ -72,6 +72,7 @@ class OrderListFragment : Fragment() { setupRecyclerView() observeOrderList() + observeViewModel() observeOrderCompletionStatus() loadOrders() } @@ -81,7 +82,8 @@ class OrderListFragment : Fragment() { onOrderClickListener = { order -> navigateToOrderDetail(order) }, - viewModel = viewModel + viewModel = viewModel, + callbacks = this // Pass this fragment as callback ) orderAdapter.setFragmentStatus(status) @@ -120,6 +122,40 @@ class OrderListFragment : Fragment() { } } + private fun observeViewModel() { + // Observe order completion + viewModel.orderCompletionStatus.observe(viewLifecycleOwner) { result -> + when (result) { + is Result.Success -> { + Toast.makeText(requireContext(), "Order completed successfully!", Toast.LENGTH_SHORT).show() + loadOrders() // Refresh here + } + is Result.Error -> { + Toast.makeText(requireContext(), "Failed: ${result.exception.message}", Toast.LENGTH_SHORT).show() + } + is Result.Loading -> { + // Show loading if needed + } + } + } + + // Observe cancel order status + viewModel.cancelOrderStatus.observe(viewLifecycleOwner) { result -> + when (result) { + is Result.Success -> { + Toast.makeText(requireContext(), "Order cancelled successfully!", Toast.LENGTH_SHORT).show() + loadOrders() // Refresh here + } + is Result.Error -> { + Toast.makeText(requireContext(), "Failed to cancel: ${result.exception.message}", Toast.LENGTH_SHORT).show() + } + is Result.Loading -> { + // Show loading if needed + } + } + } + } + private fun loadOrders() { // Simple - just call getOrderList for any status including "all" viewModel.getOrderList(status) @@ -142,6 +178,30 @@ class OrderListFragment : Fragment() { detailOrderLauncher.launch(intent) } + + + override fun onOrderCancelled(orderId: String, success: Boolean, message: String) { + if (success) { + Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() + loadOrders() // Refresh the list + } else { + Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() + } + } + + override fun onOrderCompleted(orderId: Int, success: Boolean, message: String) { + if (success) { + Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() + loadOrders() // Refresh the list + } else { + Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() + } + } + + override fun onShowLoading(show: Boolean) { + binding.progressBar.visibility = if (show) View.VISIBLE else View.GONE + } + override fun onDestroyView() { super.onDestroyView() _binding = null diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderViewPageAdapter.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderViewPageAdapter.kt index 615f7a1..146100d 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderViewPageAdapter.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderViewPageAdapter.kt @@ -11,8 +11,8 @@ class OrderViewPagerAdapter( // Define all possible order statuses private val orderStatuses = listOf( "all", // All orders - "pending", // Menunggu Tagihan - "unpaid", // Belum Dibayar + "unpaid", // Menunggu Tagihan + "paid", // Belum Dibayar "processed", // Diproses "shipped", // Dikirim "completed", // Selesai diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/detailorder/DetailOrderStatusActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/detailorder/DetailOrderStatusActivity.kt index 4e5d6b4..d68dd35 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/detailorder/DetailOrderStatusActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/detailorder/DetailOrderStatusActivity.kt @@ -234,8 +234,8 @@ class DetailOrderStatusActivity : AppCompatActivity() { // Set status header val statusText = when(status) { - "pending" -> "Belum Bayar" "unpaid" -> "Belum Bayar" + "paid" -> "Sudah Dibayar" "processed" -> "Diproses" "shipped" -> "Dikirim" "delivered" -> "Diterima" @@ -248,22 +248,6 @@ class DetailOrderStatusActivity : AppCompatActivity() { Log.d(TAG, "adjustButtonsBasedOnStatus: Status header set to '$statusText'") when (status) { - "pending"->{ - binding.tvStatusHeader.text = "Menunggu Tagihan" - binding.tvStatusNote.visibility = View.VISIBLE - binding.tvStatusNote.text = "Pesanan ini harus dibayar sebelum ${formatDatePay(orders.updatedAt)}" - - // Set buttons - binding.btnSecondary.apply { - visibility = View.VISIBLE - text = "Batalkan Pesanan" - setOnClickListener { - Log.d(TAG, "Cancel Order button clicked") - showCancelOrderBottomSheet(orders.orderId) - viewModel.getOrderDetails(orders.orderId) - } - } - } "unpaid" -> { Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for pending/unpaid order") @@ -295,7 +279,25 @@ class DetailOrderStatusActivity : AppCompatActivity() { } } } + "paid" -> { + Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for pending/unpaid order") + // Show status note + binding.tvStatusHeader.text = "Sudah Dibayar" + binding.tvStatusNote.visibility = View.VISIBLE + binding.tvStatusNote.text = "Menunggu pesanan dikonfirmasi penjual ${formatDatePay(orders.updatedAt)}" + + // Set buttons + binding.btnSecondary.apply { + visibility = View.VISIBLE + text = "Batalkan Pesanan" + setOnClickListener { + Log.d(TAG, "Cancel Order button clicked") + showCancelOrderDialog(orders.orderId.toString()) + viewModel.getOrderDetails(orders.orderId) + } + } + } "processed" -> { Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for processed order") diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/product/storeDetail/StoreDetailActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/product/storeDetail/StoreDetailActivity.kt index 50ebbe2..73a64b0 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/product/storeDetail/StoreDetailActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/product/storeDetail/StoreDetailActivity.kt @@ -11,7 +11,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ViewCompat import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat -import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.GridLayoutManager import com.alya.ecommerce_serang.BuildConfig.BASE_URL import com.alya.ecommerce_serang.R import com.alya.ecommerce_serang.data.api.dto.ProductsItem @@ -169,11 +169,7 @@ class StoreDetailActivity : AppCompatActivity() { binding.rvProducts.apply { adapter = productAdapter - layoutManager = LinearLayoutManager( - context, - LinearLayoutManager.HORIZONTAL, - false - ) + layoutManager = GridLayoutManager(context, 2) } } diff --git a/app/src/main/res/layout/activity_store_detail.xml b/app/src/main/res/layout/activity_store_detail.xml index 1b2fdce..0e71ad2 100644 --- a/app/src/main/res/layout/activity_store_detail.xml +++ b/app/src/main/res/layout/activity_store_detail.xml @@ -158,14 +158,13 @@ + app:spanCount="2" + tools:listitem="@layout/item_product_grid" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 3372ca4..af75ae6 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -15,34 +15,25 @@ android:layout_marginTop="16dp" app:layout_constraintTop_toTopOf="parent" /> - - - - - - - - - - - - - + android:layout_height="wrap_content" + android:paddingBottom="16dp"> + - + + + tools:listitem="@layout/item_product_grid" /> + - + Batas Tagihan Batas Pembayaran Batas Pengiriman - Semua Pesanan + Batas Konfirmasi Penjual Semua Pesanan Semua Pesanan Tanggal Pesanan Sampai