mirror of
https://github.com/shaulascr/ecommerce_serang.git
synced 2025-08-10 09:22:21 +00:00
update refresh change tab
This commit is contained in:
@ -10,6 +10,7 @@ import com.alya.ecommerce_serang.data.api.dto.CompletedOrderRequest
|
|||||||
import com.alya.ecommerce_serang.data.api.dto.OrdersItem
|
import com.alya.ecommerce_serang.data.api.dto.OrdersItem
|
||||||
import com.alya.ecommerce_serang.data.api.response.customer.order.CancelOrderResponse
|
import com.alya.ecommerce_serang.data.api.response.customer.order.CancelOrderResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.customer.order.OrderListItemsItem
|
import com.alya.ecommerce_serang.data.api.response.customer.order.OrderListItemsItem
|
||||||
|
import com.alya.ecommerce_serang.data.api.response.customer.order.OrderListResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.customer.order.Orders
|
import com.alya.ecommerce_serang.data.api.response.customer.order.Orders
|
||||||
import com.alya.ecommerce_serang.data.api.response.order.CompletedOrderResponse
|
import com.alya.ecommerce_serang.data.api.response.order.CompletedOrderResponse
|
||||||
import com.alya.ecommerce_serang.data.repository.OrderRepository
|
import com.alya.ecommerce_serang.data.repository.OrderRepository
|
||||||
@ -18,6 +19,13 @@ import com.alya.ecommerce_serang.ui.order.address.ViewState
|
|||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
import kotlinx.coroutines.coroutineScope
|
import kotlinx.coroutines.coroutineScope
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.flatMapLatest
|
||||||
|
import kotlinx.coroutines.flow.flow
|
||||||
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
@ -29,8 +37,8 @@ class HistoryViewModel(private val repository: OrderRepository) : ViewModel() {
|
|||||||
private const val TAG = "HistoryViewModel"
|
private const val TAG = "HistoryViewModel"
|
||||||
}
|
}
|
||||||
|
|
||||||
private val _orders = MutableLiveData<ViewState<List<OrdersItem>>>()
|
// private val _orders = MutableLiveData<ViewState<List<OrdersItem>>>()
|
||||||
val orders: LiveData<ViewState<List<OrdersItem>>> = _orders
|
// val orders: LiveData<ViewState<List<OrdersItem>>> = _orders
|
||||||
|
|
||||||
private val _orderCompletionStatus = MutableLiveData<Result<CompletedOrderResponse>>()
|
private val _orderCompletionStatus = MutableLiveData<Result<CompletedOrderResponse>>()
|
||||||
val orderCompletionStatus: LiveData<Result<CompletedOrderResponse>> = _orderCompletionStatus
|
val orderCompletionStatus: LiveData<Result<CompletedOrderResponse>> = _orderCompletionStatus
|
||||||
@ -59,81 +67,156 @@ class HistoryViewModel(private val repository: OrderRepository) : ViewModel() {
|
|||||||
private val _error = MutableLiveData<String>()
|
private val _error = MutableLiveData<String>()
|
||||||
val error: LiveData<String> get() = _error
|
val error: LiveData<String> get() = _error
|
||||||
|
|
||||||
fun getOrderList(status: String) {
|
private val _selectedStatus = MutableStateFlow("all")
|
||||||
_orders.value = ViewState.Loading
|
val selectedStatus: StateFlow<String> = _selectedStatus.asStateFlow()
|
||||||
viewModelScope.launch {
|
|
||||||
try {
|
val orders: StateFlow<ViewState<List<OrdersItem>>> =
|
||||||
if (status == "all") {
|
_selectedStatus
|
||||||
// Get all orders by combining all statuses
|
.flatMapLatest { status ->
|
||||||
getAllOrdersCombined()
|
flow<ViewState<List<OrdersItem>>> {
|
||||||
} else {
|
Log.d(TAG, "⏳ Loading orders for status = $status")
|
||||||
// Get orders for specific status
|
emit(ViewState.Loading)
|
||||||
when (val result = repository.getOrderList(status)) {
|
|
||||||
is Result.Success -> {
|
val viewState =
|
||||||
_orders.value = ViewState.Success(result.data.orders)
|
if (status == "all") {
|
||||||
Log.d(TAG, "Orders loaded successfully: ${result.data.orders.size} items")
|
getAllOrdersCombined().also {
|
||||||
|
Log.d(TAG, "✅ Combined orders size = ${(it as? ViewState.Success)?.data?.size}")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
when (val r = repository.getOrderList(status)) {
|
||||||
|
|
||||||
|
is Result.Loading -> {
|
||||||
|
Log.d(TAG, " repository.getOrderList($status) → Loading")
|
||||||
|
ViewState.Loading
|
||||||
|
}
|
||||||
|
|
||||||
|
is Result.Success -> {
|
||||||
|
Log.d(TAG, "✅ repository.getOrderList($status) success, size = ${r.data.orders.size}")
|
||||||
|
// Tag each order so the fragment’s filter works
|
||||||
|
val tagged = r.data.orders.onEach { it.displayStatus = status }
|
||||||
|
ViewState.Success(tagged)
|
||||||
|
}
|
||||||
|
|
||||||
|
is Result.Error -> {
|
||||||
|
Log.e(TAG, "❌ repository.getOrderList($status) error = ${r.exception.message}")
|
||||||
|
ViewState.Error(r.exception.message ?: "Unknown error")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
is Result.Error -> {
|
|
||||||
_orders.value = ViewState.Error(result.exception.message ?: "Unknown error occurred")
|
emit(viewState)
|
||||||
Log.e(TAG, "Error loading orders", result.exception)
|
|
||||||
}
|
|
||||||
is Result.Loading -> {
|
|
||||||
// Keep loading state
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
|
||||||
_orders.value = ViewState.Error("An unexpected error occurred: ${e.message}")
|
|
||||||
Log.e(TAG, "Exception in getOrderList", e)
|
|
||||||
}
|
}
|
||||||
}
|
.stateIn(
|
||||||
}
|
viewModelScope,
|
||||||
|
SharingStarted.WhileSubscribed(5_000),
|
||||||
|
ViewState.Loading // ② initial value, still fine
|
||||||
|
)
|
||||||
|
|
||||||
private suspend fun getAllOrdersCombined() {
|
|
||||||
try {
|
|
||||||
val allStatuses = listOf("unpaid", "paid", "processed", "shipped", "completed", "canceled")
|
|
||||||
val allOrders = mutableListOf<OrdersItem>()
|
|
||||||
|
|
||||||
// Use coroutineScope to allow launching async blocks
|
// fun getOrderList(status: String) {
|
||||||
coroutineScope {
|
// _orders.value = ViewState.Loading
|
||||||
val deferreds = allStatuses.map { status ->
|
// viewModelScope.launch {
|
||||||
|
// try {
|
||||||
|
// if (status == "all") {
|
||||||
|
// // Get all orders by combining all statuses
|
||||||
|
// getAllOrdersCombined()
|
||||||
|
// } else {
|
||||||
|
// // Get orders for specific status
|
||||||
|
// when (val result = repository.getOrderList(status)) {
|
||||||
|
// is Result.Success -> {
|
||||||
|
// _orders.value = ViewState.Success(result.data.orders)
|
||||||
|
// Log.d(TAG, "Orders loaded successfully: ${result.data.orders.size} items")
|
||||||
|
// }
|
||||||
|
// is Result.Error -> {
|
||||||
|
// _orders.value = ViewState.Error(result.exception.message ?: "Unknown error occurred")
|
||||||
|
// Log.e(TAG, "Error loading orders", result.exception)
|
||||||
|
// }
|
||||||
|
// is Result.Loading -> {
|
||||||
|
// // Keep loading state
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } catch (e: Exception) {
|
||||||
|
// _orders.value = ViewState.Error("An unexpected error occurred: ${e.message}")
|
||||||
|
// Log.e(TAG, "Exception in getOrderList", e)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private suspend fun getAllOrdersCombined() {
|
||||||
|
// try {
|
||||||
|
// val allStatuses = listOf("unpaid", "paid", "processed", "shipped", "completed", "canceled")
|
||||||
|
// val allOrders = mutableListOf<OrdersItem>()
|
||||||
|
//
|
||||||
|
// // Use coroutineScope to allow launching async blocks
|
||||||
|
// coroutineScope {
|
||||||
|
// val deferreds = allStatuses.map { status ->
|
||||||
|
// async {
|
||||||
|
// when (val result = repository.getOrderList(status)) {
|
||||||
|
// is Result.Success -> {
|
||||||
|
// // Tag each order with the status it was fetched from
|
||||||
|
// result.data.orders.onEach { it.displayStatus = status }
|
||||||
|
// }
|
||||||
|
// is Result.Error -> {
|
||||||
|
// Log.e(TAG, "Error loading orders for status $status", result.exception)
|
||||||
|
// emptyList<OrdersItem>()
|
||||||
|
// }
|
||||||
|
// is Result.Loading -> emptyList<OrdersItem>()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Await all results and combine
|
||||||
|
// deferreds.awaitAll().forEach { orders ->
|
||||||
|
// allOrders.addAll(orders)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Sort orders
|
||||||
|
// val sortedOrders = allOrders.sortedByDescending { order ->
|
||||||
|
// try {
|
||||||
|
// SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault()).parse(order.createdAt)
|
||||||
|
// } catch (e: Exception) {
|
||||||
|
// null
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// _orders.value = ViewState.Success(sortedOrders)
|
||||||
|
// Log.d(TAG, "All orders loaded successfully: ${sortedOrders.size} items")
|
||||||
|
//
|
||||||
|
// } catch (e: Exception) {
|
||||||
|
// _orders.value = ViewState.Error("An unexpected error occurred: ${e.message}")
|
||||||
|
// Log.e(TAG, "Exception in getAllOrdersCombined", e)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
private suspend fun getAllOrdersCombined(): ViewState<List<OrdersItem>> = try {
|
||||||
|
val statuses = listOf("unpaid", "paid", "processed", "shipped", "completed", "canceled")
|
||||||
|
|
||||||
|
val all = coroutineScope {
|
||||||
|
statuses
|
||||||
|
.map { status ->
|
||||||
async {
|
async {
|
||||||
when (val result = repository.getOrderList(status)) {
|
when (val r = repository.getOrderList(status)) {
|
||||||
is Result.Success -> {
|
is Result.Success -> r.data.orders.onEach { it.displayStatus = status }
|
||||||
// Tag each order with the status it was fetched from
|
else -> emptyList()
|
||||||
result.data.orders.onEach { it.displayStatus = status }
|
|
||||||
}
|
|
||||||
is Result.Error -> {
|
|
||||||
Log.e(TAG, "Error loading orders for status $status", result.exception)
|
|
||||||
emptyList<OrdersItem>()
|
|
||||||
}
|
|
||||||
is Result.Loading -> emptyList<OrdersItem>()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.awaitAll()
|
||||||
// Await all results and combine
|
.flatten()
|
||||||
deferreds.awaitAll().forEach { orders ->
|
|
||||||
allOrders.addAll(orders)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort orders
|
|
||||||
val sortedOrders = allOrders.sortedByDescending { order ->
|
|
||||||
try {
|
|
||||||
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault()).parse(order.createdAt)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_orders.value = ViewState.Success(sortedOrders)
|
|
||||||
Log.d(TAG, "All orders loaded successfully: ${sortedOrders.size} items")
|
|
||||||
|
|
||||||
} catch (e: Exception) {
|
|
||||||
_orders.value = ViewState.Error("An unexpected error occurred: ${e.message}")
|
|
||||||
Log.e(TAG, "Exception in getAllOrdersCombined", e)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val sorted = all.sortedByDescending { order ->
|
||||||
|
try {
|
||||||
|
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault())
|
||||||
|
.parse(order.createdAt)
|
||||||
|
} catch (_: Exception) { null }
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewState.Success(sorted)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
ViewState.Error("Failed to load orders: ${e.message}")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun confirmOrderCompleted(orderId: Int, status: String) {
|
fun confirmOrderCompleted(orderId: Int, status: String) {
|
||||||
@ -209,9 +292,52 @@ class HistoryViewModel(private val repository: OrderRepository) : ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun refreshOrders(status: String = "all") {
|
// fun refreshOrders(status: String = "all") {
|
||||||
Log.d(TAG, "Refreshing orders with status: $status")
|
// Log.d(TAG, "Refreshing orders with status: $status")
|
||||||
// Don't set Loading here if you want to show current data while refreshing
|
// // Don't set Loading here if you want to show current data while refreshing
|
||||||
getOrderList(status)
|
// getOrderList(status)
|
||||||
|
// }
|
||||||
|
|
||||||
|
fun updateStatus(status: String, forceRefresh: Boolean = false) {
|
||||||
|
Log.d(TAG, "↪️ updateStatus(status = $status, forceRefresh = $forceRefresh)")
|
||||||
|
|
||||||
|
// No‑op guard (optional): skip if user re‑selects same tab and no refresh asked
|
||||||
|
if (_selectedStatus.value == status && !forceRefresh) {
|
||||||
|
Log.d(TAG, "🔸 Status unchanged & forceRefresh = false → skip update")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_selectedStatus.value = status
|
||||||
|
Log.d(TAG, "✅ _selectedStatus set to \"$status\"")
|
||||||
|
|
||||||
|
if (forceRefresh) {
|
||||||
|
Log.d(TAG, "🔄 forceRefresh = true → launching refresh()")
|
||||||
|
viewModelScope.launch { refresh(status) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun refresh(status: String) {
|
||||||
|
Log.d(TAG, "⏳ refresh(\"$status\") started")
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (status == "all") {
|
||||||
|
Log.d(TAG, "🌐 Calling getAllOrdersCombined()")
|
||||||
|
getAllOrdersCombined() // network → cache
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "🌐 repository.getOrderList(\"$status\")")
|
||||||
|
repository.getOrderList(status) // network → cache
|
||||||
|
}
|
||||||
|
Log.d(TAG, "✅ refresh(\"$status\") completed (repository updated)")
|
||||||
|
// Flow that watches DB/cache will emit automatically
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "❌ refresh(\"$status\") failed: ${e.message}", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Result<OrderListResponse>.toViewState(): ViewState<List<OrdersItem>> =
|
||||||
|
when (this) {
|
||||||
|
is Result.Success -> ViewState.Success(data.orders)
|
||||||
|
is Result.Error -> ViewState.Error(exception.message ?: "Unknown error")
|
||||||
|
is Result.Loading -> ViewState.Loading // should rarely reach UI
|
||||||
|
}
|
||||||
}
|
}
|
@ -195,7 +195,7 @@ class OrderHistoryAdapter(
|
|||||||
text = itemView.context.getString(R.string.canceled_order_btn)
|
text = itemView.context.getString(R.string.canceled_order_btn)
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
showCancelOrderDialog(order.orderId.toString())
|
showCancelOrderDialog(order.orderId.toString())
|
||||||
viewModel.refreshOrders()
|
// viewModel.refreshOrders()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// deadlineDate.apply {
|
// deadlineDate.apply {
|
||||||
@ -238,7 +238,7 @@ class OrderHistoryAdapter(
|
|||||||
text = itemView.context.getString(R.string.claim_complaint)
|
text = itemView.context.getString(R.string.claim_complaint)
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
showCancelOrderDialog(order.orderId.toString())
|
showCancelOrderDialog(order.orderId.toString())
|
||||||
viewModel.refreshOrders()
|
// viewModel.refreshOrders()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
btnRight.apply {
|
btnRight.apply {
|
||||||
@ -249,7 +249,7 @@ class OrderHistoryAdapter(
|
|||||||
|
|
||||||
// Call ViewModel
|
// Call ViewModel
|
||||||
viewModel.confirmOrderCompleted(order.orderId, "completed")
|
viewModel.confirmOrderCompleted(order.orderId, "completed")
|
||||||
viewModel.refreshOrders()
|
// viewModel.refreshOrders()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,8 +5,13 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.activityViewModels
|
||||||
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
import com.alya.ecommerce_serang.R
|
import com.alya.ecommerce_serang.R
|
||||||
|
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
|
||||||
|
import com.alya.ecommerce_serang.data.repository.OrderRepository
|
||||||
import com.alya.ecommerce_serang.databinding.FragmentOrderHistoryBinding
|
import com.alya.ecommerce_serang.databinding.FragmentOrderHistoryBinding
|
||||||
|
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
||||||
import com.alya.ecommerce_serang.utils.SessionManager
|
import com.alya.ecommerce_serang.utils.SessionManager
|
||||||
import com.google.android.material.tabs.TabLayoutMediator
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
|
|
||||||
@ -16,6 +21,12 @@ class OrderHistoryFragment : Fragment() {
|
|||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
private lateinit var sessionManager: SessionManager
|
private lateinit var sessionManager: SessionManager
|
||||||
|
|
||||||
|
private val historyVm: HistoryViewModel by activityViewModels {
|
||||||
|
BaseViewModelFactory {
|
||||||
|
val api = ApiConfig.getApiService(SessionManager(requireContext()))
|
||||||
|
HistoryViewModel(OrderRepository(api))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private lateinit var viewPagerAdapter: OrderViewPagerAdapter
|
private lateinit var viewPagerAdapter: OrderViewPagerAdapter
|
||||||
|
|
||||||
@ -33,6 +44,8 @@ class OrderHistoryFragment : Fragment() {
|
|||||||
sessionManager = SessionManager(requireContext())
|
sessionManager = SessionManager(requireContext())
|
||||||
|
|
||||||
setupViewPager()
|
setupViewPager()
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupViewPager() {
|
private fun setupViewPager() {
|
||||||
@ -53,6 +66,16 @@ class OrderHistoryFragment : Fragment() {
|
|||||||
else -> "Tab $position"
|
else -> "Tab $position"
|
||||||
}
|
}
|
||||||
}.attach()
|
}.attach()
|
||||||
|
|
||||||
|
binding.viewPager.registerOnPageChangeCallback(
|
||||||
|
object : ViewPager2.OnPageChangeCallback() {
|
||||||
|
override fun onPageSelected(position: Int) {
|
||||||
|
val status = viewPagerAdapter.orderStatuses[position]
|
||||||
|
/* setStatus() is the API we added earlier; TRUE → always re‑query */
|
||||||
|
historyVm.updateStatus(status, forceRefresh = true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
@ -8,8 +8,10 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.alya.ecommerce_serang.data.api.dto.OrdersItem
|
import com.alya.ecommerce_serang.data.api.dto.OrdersItem
|
||||||
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
|
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
|
||||||
@ -27,17 +29,26 @@ class OrderListFragment : Fragment(), OrderHistoryAdapter.OrderActionCallbacks {
|
|||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
private lateinit var sessionManager: SessionManager
|
private lateinit var sessionManager: SessionManager
|
||||||
|
|
||||||
private val viewModel: HistoryViewModel by viewModels {
|
private val viewModel: HistoryViewModel by activityViewModels {
|
||||||
BaseViewModelFactory {
|
BaseViewModelFactory {
|
||||||
val apiService = ApiConfig.getApiService(sessionManager)
|
val api = ApiConfig.getApiService(SessionManager(requireContext()))
|
||||||
val orderRepository = OrderRepository(apiService)
|
HistoryViewModel(OrderRepository(api))
|
||||||
HistoryViewModel(orderRepository)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var orderAdapter: OrderHistoryAdapter
|
private lateinit var orderAdapter: OrderHistoryAdapter
|
||||||
|
|
||||||
private var status: String = "all"
|
private var status: String = "all"
|
||||||
|
|
||||||
|
private val detailOrderLauncher = registerForActivityResult(
|
||||||
|
ActivityResultContracts.StartActivityForResult()
|
||||||
|
) { result ->
|
||||||
|
if (result.resultCode == Activity.RESULT_OK) {
|
||||||
|
/* force‑refresh the current tab */
|
||||||
|
viewModel.updateStatus(status, forceRefresh = true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val ARG_STATUS = "status"
|
private const val ARG_STATUS = "status"
|
||||||
|
|
||||||
@ -73,8 +84,8 @@ class OrderListFragment : Fragment(), OrderHistoryAdapter.OrderActionCallbacks {
|
|||||||
setupRecyclerView()
|
setupRecyclerView()
|
||||||
observeOrderList()
|
observeOrderList()
|
||||||
observeViewModel()
|
observeViewModel()
|
||||||
observeOrderCompletionStatus()
|
// observeOrderCompletionStatus()
|
||||||
loadOrders()
|
// loadOrders()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupRecyclerView() {
|
private fun setupRecyclerView() {
|
||||||
@ -96,27 +107,50 @@ class OrderListFragment : Fragment(), OrderHistoryAdapter.OrderActionCallbacks {
|
|||||||
|
|
||||||
private fun observeOrderList() {
|
private fun observeOrderList() {
|
||||||
// Now we only need to observe one LiveData for all cases
|
// Now we only need to observe one LiveData for all cases
|
||||||
viewModel.orders.observe(viewLifecycleOwner) { result ->
|
// viewModel.orders.observe(viewLifecycleOwner) { result ->
|
||||||
when (result) {
|
// when (result) {
|
||||||
is ViewState.Success -> {
|
// is ViewState.Success -> {
|
||||||
binding.progressBar.visibility = View.GONE
|
// binding.progressBar.visibility = View.GONE
|
||||||
|
//
|
||||||
if (result.data.isNullOrEmpty()) {
|
// if (result.data.isNullOrEmpty()) {
|
||||||
binding.tvEmptyState.visibility = View.VISIBLE
|
// binding.tvEmptyState.visibility = View.VISIBLE
|
||||||
binding.rvOrders.visibility = View.GONE
|
// binding.rvOrders.visibility = View.GONE
|
||||||
} else {
|
// } else {
|
||||||
binding.tvEmptyState.visibility = View.GONE
|
// binding.tvEmptyState.visibility = View.GONE
|
||||||
binding.rvOrders.visibility = View.VISIBLE
|
// binding.rvOrders.visibility = View.VISIBLE
|
||||||
orderAdapter.submitList(result.data)
|
// orderAdapter.submitList(result.data)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// is ViewState.Error -> {
|
||||||
|
// binding.progressBar.visibility = View.GONE
|
||||||
|
// binding.tvEmptyState.visibility = View.VISIBLE
|
||||||
|
// Toast.makeText(requireContext(), result.message, Toast.LENGTH_SHORT).show()
|
||||||
|
// }
|
||||||
|
// is ViewState.Loading -> {
|
||||||
|
// binding.progressBar.visibility = View.VISIBLE
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
viewLifecycleOwner.lifecycleScope.launchWhenStarted {
|
||||||
|
viewModel.orders.collect { state ->
|
||||||
|
when (state) {
|
||||||
|
is ViewState.Loading -> {
|
||||||
|
binding.progressBar.isVisible = true
|
||||||
|
}
|
||||||
|
is ViewState.Error -> {
|
||||||
|
binding.progressBar.isVisible = false
|
||||||
|
binding.tvEmptyState.isVisible = true
|
||||||
|
binding.rvOrders.isVisible = false
|
||||||
|
Toast.makeText(requireContext(), state.message, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
is ViewState.Success -> {
|
||||||
|
binding.progressBar.isVisible = false
|
||||||
|
val list = state.data
|
||||||
|
.filter { status == "all" || it.displayStatus == status }
|
||||||
|
binding.tvEmptyState.isVisible = list.isEmpty()
|
||||||
|
binding.rvOrders.isVisible = list.isNotEmpty()
|
||||||
|
orderAdapter.submitList(list)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
is ViewState.Error -> {
|
|
||||||
binding.progressBar.visibility = View.GONE
|
|
||||||
binding.tvEmptyState.visibility = View.VISIBLE
|
|
||||||
Toast.makeText(requireContext(), result.message, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
is ViewState.Loading -> {
|
|
||||||
binding.progressBar.visibility = View.VISIBLE
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,51 +158,78 @@ class OrderListFragment : Fragment(), OrderHistoryAdapter.OrderActionCallbacks {
|
|||||||
|
|
||||||
private fun observeViewModel() {
|
private fun observeViewModel() {
|
||||||
// Observe order completion
|
// 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
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
viewModel.orderCompletionStatus.observe(viewLifecycleOwner) { result ->
|
viewModel.orderCompletionStatus.observe(viewLifecycleOwner) { result ->
|
||||||
when (result) {
|
when (result) {
|
||||||
is Result.Success -> {
|
is Result.Success -> {
|
||||||
Toast.makeText(requireContext(), "Order completed successfully!", Toast.LENGTH_SHORT).show()
|
Toast.makeText(requireContext(),
|
||||||
loadOrders() // Refresh here
|
"Order completed!", Toast.LENGTH_SHORT).show()
|
||||||
}
|
viewModel.updateStatus(status, forceRefresh = true)
|
||||||
is Result.Error -> {
|
|
||||||
Toast.makeText(requireContext(), "Failed: ${result.exception.message}", Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
is Result.Loading -> {
|
|
||||||
// Show loading if needed
|
|
||||||
}
|
}
|
||||||
|
is Result.Error ->
|
||||||
|
Toast.makeText(requireContext(),
|
||||||
|
"Failed: ${result.exception.message}", Toast.LENGTH_SHORT).show()
|
||||||
|
else -> { /* Loading → no UI change */ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Observe cancel order status
|
|
||||||
viewModel.cancelOrderStatus.observe(viewLifecycleOwner) { result ->
|
viewModel.cancelOrderStatus.observe(viewLifecycleOwner) { result ->
|
||||||
when (result) {
|
when (result) {
|
||||||
is Result.Success -> {
|
is Result.Success -> {
|
||||||
Toast.makeText(requireContext(), "Order cancelled successfully!", Toast.LENGTH_SHORT).show()
|
Toast.makeText(requireContext(),
|
||||||
loadOrders() // Refresh here
|
"Order cancelled!", Toast.LENGTH_SHORT).show()
|
||||||
}
|
viewModel.updateStatus(status, forceRefresh = true)
|
||||||
is Result.Error -> {
|
|
||||||
Toast.makeText(requireContext(), "Failed to cancel: ${result.exception.message}", Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
is Result.Loading -> {
|
|
||||||
// Show loading if needed
|
|
||||||
}
|
}
|
||||||
|
is Result.Error ->
|
||||||
|
Toast.makeText(requireContext(),
|
||||||
|
"Failed: ${result.exception.message}", Toast.LENGTH_SHORT).show()
|
||||||
|
else -> { /* Loading */ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadOrders() {
|
// private fun loadOrders() {
|
||||||
// Simple - just call getOrderList for any status including "all"
|
// // Simple - just call getOrderList for any status including "all"
|
||||||
viewModel.getOrderList(status)
|
// viewModel.getOrderList(status)
|
||||||
}
|
// }
|
||||||
|
|
||||||
private val detailOrderLauncher = registerForActivityResult(
|
// private val detailOrderLauncher = registerForActivityResult(
|
||||||
ActivityResultContracts.StartActivityForResult()
|
// ActivityResultContracts.StartActivityForResult()
|
||||||
) { result ->
|
// ) { result ->
|
||||||
if (result.resultCode == Activity.RESULT_OK) {
|
// if (result.resultCode == Activity.RESULT_OK) {
|
||||||
// Refresh order list when returning with OK result
|
// // Refresh order list when returning with OK result
|
||||||
loadOrders()
|
//// loadOrders()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
private fun navigateToOrderDetail(order: OrdersItem) {
|
private fun navigateToOrderDetail(order: OrdersItem) {
|
||||||
val intent = Intent(requireContext(), DetailOrderStatusActivity::class.java).apply {
|
val intent = Intent(requireContext(), DetailOrderStatusActivity::class.java).apply {
|
||||||
@ -183,7 +244,9 @@ class OrderListFragment : Fragment(), OrderHistoryAdapter.OrderActionCallbacks {
|
|||||||
override fun onOrderCancelled(orderId: String, success: Boolean, message: String) {
|
override fun onOrderCancelled(orderId: String, success: Boolean, message: String) {
|
||||||
if (success) {
|
if (success) {
|
||||||
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
|
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
|
||||||
loadOrders() // Refresh the list
|
// loadOrders() // Refresh the list
|
||||||
|
if (success) viewModel.updateStatus(status, forceRefresh = true)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
|
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
@ -192,7 +255,8 @@ class OrderListFragment : Fragment(), OrderHistoryAdapter.OrderActionCallbacks {
|
|||||||
override fun onOrderCompleted(orderId: Int, success: Boolean, message: String) {
|
override fun onOrderCompleted(orderId: Int, success: Boolean, message: String) {
|
||||||
if (success) {
|
if (success) {
|
||||||
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
|
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
|
||||||
loadOrders() // Refresh the list
|
// loadOrders() // Refresh the list
|
||||||
|
if (success) viewModel.updateStatus(status, forceRefresh = true)
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
|
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
@ -207,20 +271,20 @@ class OrderListFragment : Fragment(), OrderHistoryAdapter.OrderActionCallbacks {
|
|||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun observeOrderCompletionStatus() {
|
// private fun observeOrderCompletionStatus() {
|
||||||
viewModel.orderCompletionStatus.observe(viewLifecycleOwner) { result ->
|
// viewModel.orderCompletionStatus.observe(viewLifecycleOwner) { result ->
|
||||||
when (result) {
|
// when (result) {
|
||||||
is Result.Loading -> {
|
// is Result.Loading -> {
|
||||||
// Handle loading state if needed
|
// // Handle loading state if needed
|
||||||
}
|
// }
|
||||||
is Result.Success -> {
|
// is Result.Success -> {
|
||||||
Toast.makeText(requireContext(), "Order completed successfully!", Toast.LENGTH_SHORT).show()
|
// Toast.makeText(requireContext(), "Order completed successfully!", Toast.LENGTH_SHORT).show()
|
||||||
loadOrders()
|
//// loadOrders()
|
||||||
}
|
// }
|
||||||
is Result.Error -> {
|
// is Result.Error -> {
|
||||||
Toast.makeText(requireContext(), "Failed to complete order: ${result.exception.message}", Toast.LENGTH_SHORT).show()
|
// Toast.makeText(requireContext(), "Failed to complete order: ${result.exception.message}", Toast.LENGTH_SHORT).show()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
@ -9,7 +9,7 @@ class OrderViewPagerAdapter(
|
|||||||
) : FragmentStateAdapter(fragmentActivity) {
|
) : FragmentStateAdapter(fragmentActivity) {
|
||||||
|
|
||||||
// Define all possible order statuses
|
// Define all possible order statuses
|
||||||
private val orderStatuses = listOf(
|
val orderStatuses = listOf(
|
||||||
"all", // All orders
|
"all", // All orders
|
||||||
"unpaid", // Menunggu Tagihan
|
"unpaid", // Menunggu Tagihan
|
||||||
"paid", // Belum Dibayar
|
"paid", // Belum Dibayar
|
||||||
|
Reference in New Issue
Block a user