diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/auth/LoginActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/LoginActivity.kt index 6013739..5c03fe7 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/auth/LoginActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/LoginActivity.kt @@ -43,27 +43,10 @@ class LoginActivity : AppCompatActivity() { WindowCompat.setDecorFitsSystemWindows(window, false) enableEdgeToEdge() -// ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets -> -// val systemBars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) -// view.setPadding( -// systemBars.left, -// systemBars.top, -// systemBars.right, -// systemBars.bottom -// ) -// windowInsets -// } - -// onBackPressedDispatcher.addCallback(this) { -// // Handle the back button event -// } - setupListeners() observeLoginState() FirebaseApp.initializeApp(this) - - // Request FCM token at app startup } private fun setupListeners() { diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/CheckoutViewModel.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/CheckoutViewModel.kt index f263122..abf1471 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/CheckoutViewModel.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/CheckoutViewModel.kt @@ -145,6 +145,8 @@ class CheckoutViewModel(private val repository: OrderRepository) : ViewModel() { isReseller = isWholesaleMap.any { it.value } ) + Log.d(TAG, "Cek is reseller: ${orderRequest.isReseller}") + _checkoutData.value = CheckoutData( orderRequest = orderRequest, productName = matchingItems.first().productName, @@ -378,6 +380,7 @@ class CheckoutViewModel(private val repository: OrderRepository) : ViewModel() { } else { // For Cart checkout, use the standard order endpoint val cartRequest = data.orderRequest as OrderRequest + Log.d(TAG, "data: ${cartRequest.cartItemId}") repository.createOrder(cartRequest) } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/ProvinceAdapter.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/ProvinceAdapter.kt index 727ccb3..00592ec 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/ProvinceAdapter.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/ProvinceAdapter.kt @@ -4,6 +4,7 @@ import android.content.Context import android.util.Log import android.widget.ArrayAdapter import android.widget.Spinner +import com.alya.ecommerce_serang.R import com.alya.ecommerce_serang.data.api.response.customer.order.CitiesItem import com.alya.ecommerce_serang.data.api.response.customer.order.ProvincesItem import com.alya.ecommerce_serang.data.api.response.customer.order.SubdistrictsItem @@ -134,23 +135,8 @@ class BankAdapter( } private fun loadHardcodedData() { - val defaultBanks = listOf( - BankItem("Bank Mandiri", "008", "PT Bank Mandiri (Persero) Tbk"), - BankItem("Bank BRI", "002", "PT Bank Rakyat Indonesia (Persero) Tbk"), - BankItem("Bank BCA", "014", "PT Bank Central Asia Tbk"), - BankItem("Bank BNI", "009", "PT Bank Negara Indonesia (Persero) Tbk"), - BankItem("Bank BTN", "200", "PT Bank Tabungan Negara (Persero) Tbk"), - BankItem("Bank CIMB Niaga", "022", "PT Bank CIMB Niaga Tbk"), - BankItem("Bank Danamon", "011", "PT Bank Danamon Indonesia Tbk"), - BankItem("Bank Permata", "013", "PT Bank Permata Tbk"), - BankItem("Bank OCBC NISP", "028", "PT Bank OCBC NISP Tbk"), - BankItem("Bank Maybank", "016", "PT Bank Maybank Indonesia Tbk"), - BankItem("Bank Panin", "019", "PT Bank Panin Dubai Syariah Tbk"), - BankItem("Bank UOB", "023", "PT Bank UOB Indonesia"), - BankItem("Bank Mega", "426", "PT Bank Mega Tbk"), - BankItem("Bank Bukopin", "441", "PT Bank Bukopin Tbk"), - BankItem("Bank BJB", "110", "PT Bank Pembangunan Daerah Jawa Barat dan Banten Tbk") - ) + val bankNames = context.resources.getStringArray(R.array.bank_names) + val defaultBanks = bankNames.map { BankItem(bankName = it) } updateData(defaultBanks) } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/HistoryActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/HistoryActivity.kt index 7027991..d7a9911 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/HistoryActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/HistoryActivity.kt @@ -27,7 +27,6 @@ class HistoryActivity : AppCompatActivity() { } } - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityHistoryBinding.inflate(layoutInflater) 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 a2a18af..702d3f3 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 @@ -37,9 +37,6 @@ class HistoryViewModel(private val repository: OrderRepository) : ViewModel() { private const val TAG = "HistoryViewModel" } -// private val _orders = MutableLiveData>>() -// val orders: LiveData>> = _orders - private val _orderCompletionStatus = MutableLiveData>() val orderCompletionStatus: LiveData> = _orderCompletionStatus @@ -113,83 +110,6 @@ class HistoryViewModel(private val repository: OrderRepository) : ViewModel() { ViewState.Loading // ② initial value, still fine ) - -// fun getOrderList(status: String) { -// _orders.value = ViewState.Loading -// 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() -// -// // 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() -// } -// is Result.Loading -> emptyList() -// } -// } -// } -// -// // 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> = try { val statuses = listOf("unpaid", "paid", "processed", "shipped", "completed", "canceled") @@ -292,11 +212,6 @@ class HistoryViewModel(private val repository: OrderRepository) : ViewModel() { } } -// fun refreshOrders(status: String = "all") { -// Log.d(TAG, "Refreshing orders with status: $status") -// // Don't set Loading here if you want to show current data while refreshing -// getOrderList(status) -// } fun updateStatus(status: String, forceRefresh: Boolean = false) { Log.d(TAG, "↪️ updateStatus(status = $status, forceRefresh = $forceRefresh)") 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 d211fa8..18f21f2 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 @@ -200,10 +200,6 @@ class OrderHistoryAdapter( // viewModel.refreshOrders() } } -// deadlineDate.apply { -// visibility = View.VISIBLE -// text = formatDatePay(order.updatedAt) -// } } "processed" -> { // Untuk status processed, tampilkan "Hubungi Penjual" @@ -215,15 +211,6 @@ class OrderHistoryAdapter( visibility = View.VISIBLE text = itemView.context.getString(R.string.dl_processed) } - // gabisa complaint -// btnLeft.apply { -// visibility = View.VISIBLE -// text = itemView.context.getString(R.string.canceled_order_btn) -// setOnClickListener { -// showCancelOrderDialog(order.orderId.toString()) -// viewModel.refreshOrders() -// } -// } } "shipped" -> { // Untuk status shipped, tampilkan "Lacak Pengiriman" dan "Terima Barang" @@ -517,14 +504,14 @@ class OrderHistoryAdapter( } else { // Log error and show a Toast instead if we can't get a FragmentManager Log.e("OrderHistoryAdapter", "Cannot show bottom sheet: Context is not a FragmentActivity") - Toast.makeText(context, "Terjadi kendala", Toast.LENGTH_SHORT).show() + Toast.makeText(context, "Terjadi kendala di batalkan pesanan", Toast.LENGTH_SHORT).show() return } } else -> { // Log error and show a Toast instead if we can't get a FragmentManager Log.e("OrderHistoryAdapter", "Cannot show bottom sheet: Context is not a FragmentActivity") - Toast.makeText(context, "Terjadi kendala", Toast.LENGTH_SHORT).show() + Toast.makeText(context, "Terjadi kendala di batalkan pesanan", Toast.LENGTH_SHORT).show() return } } @@ -549,7 +536,8 @@ class OrderHistoryAdapter( viewModel.error.observe(itemView.findViewTreeLifecycleOwner()!!) { errorMsg -> if (!errorMsg.isNullOrEmpty()) { - Toast.makeText(itemView.context, errorMsg, Toast.LENGTH_SHORT).show() + Log.e("OrderHistoryAdapter", "Error $errorMsg") + Toast.makeText(itemView.context, "Terdapat kendala di tambah ulasan", Toast.LENGTH_SHORT).show() } } @@ -585,7 +573,7 @@ class OrderHistoryAdapter( } else { Toast.makeText( itemView.context, - "No items to review", + "Tidak ada produk untuk direview", 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 0d77c05..eba6b91 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,6 @@ class OrderHistoryFragment : Fragment() { sessionManager = SessionManager(requireContext()) setupViewPager() - - } private fun setupViewPager() { @@ -67,17 +65,25 @@ class OrderHistoryFragment : Fragment() { } }.attach() + statusPage() + } + + private fun statusPage(){ 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 onResume() { + super.onResume() + statusPage() + } + override fun onDestroyView() { super.onDestroyView() _binding = null 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 82a9f3f..1c73594 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 @@ -3,6 +3,7 @@ package com.alya.ecommerce_serang.ui.order.history import android.app.Activity import android.content.Intent import android.os.Bundle +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -84,8 +85,6 @@ class OrderListFragment : Fragment(), OrderHistoryAdapter.OrderActionCallbacks { setupRecyclerView() observeOrderList() observeViewModel() -// observeOrderCompletionStatus() -// loadOrders() } private fun setupRecyclerView() { @@ -106,31 +105,6 @@ class OrderListFragment : Fragment(), OrderHistoryAdapter.OrderActionCallbacks { } private fun observeOrderList() { - // Now we only need to observe one LiveData for all cases -// viewModel.orders.observe(viewLifecycleOwner) { result -> -// when (result) { -// is ViewState.Success -> { -// binding.progressBar.visibility = View.GONE -// -// if (result.data.isNullOrEmpty()) { -// binding.tvEmptyState.visibility = View.VISIBLE -// binding.rvOrders.visibility = View.GONE -// } else { -// binding.tvEmptyState.visibility = View.GONE -// binding.rvOrders.visibility = View.VISIBLE -// 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) { @@ -141,7 +115,7 @@ class OrderListFragment : Fragment(), OrderHistoryAdapter.OrderActionCallbacks { binding.progressBar.isVisible = false binding.tvEmptyState.isVisible = true binding.rvOrders.isVisible = false - Toast.makeText(requireContext(), state.message, Toast.LENGTH_SHORT).show() + Log.e("OrderListFragment", "Error in order list: ${state.message}") } is ViewState.Success -> { binding.progressBar.isVisible = false @@ -157,47 +131,19 @@ class OrderListFragment : Fragment(), OrderHistoryAdapter.OrderActionCallbacks { } 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 -// } -// } -// } viewModel.orderCompletionStatus.observe(viewLifecycleOwner) { result -> when (result) { is Result.Success -> { Toast.makeText(requireContext(), - "Order completed!", Toast.LENGTH_SHORT).show() + "Pesanan Selesai", Toast.LENGTH_SHORT).show() + Log.d("OrderListFragment", "Order selesai") viewModel.updateStatus(status, forceRefresh = true) } is Result.Error -> - Toast.makeText(requireContext(), - "Failed: ${result.exception.message}", Toast.LENGTH_SHORT).show() +// Toast.makeText(requireContext(), +// "Failed: ${result.exception.message}", Toast.LENGTH_SHORT).show() + Log.e("OrderListFragment", "Failed: ${result.exception.message}") + else -> { /* Loading → no UI change */ } } } @@ -206,31 +152,19 @@ class OrderListFragment : Fragment(), OrderHistoryAdapter.OrderActionCallbacks { when (result) { is Result.Success -> { Toast.makeText(requireContext(), - "Order cancelled!", Toast.LENGTH_SHORT).show() + "Pesanan Dibatalkan", Toast.LENGTH_SHORT).show() + Log.d("OrderListFragment", "Order dibatalkan") viewModel.updateStatus(status, forceRefresh = true) } is Result.Error -> - Toast.makeText(requireContext(), - "Failed: ${result.exception.message}", Toast.LENGTH_SHORT).show() + Log.e("OrderListFragment", "Failed: ${result.exception.message}") +// Toast.makeText(requireContext(), +// "Failed: ${result.exception.message}", Toast.LENGTH_SHORT).show() else -> { /* Loading */ } } } } -// private fun loadOrders() { -// // Simple - just call getOrderList for any status including "all" -// viewModel.getOrderList(status) -// } - -// private val detailOrderLauncher = registerForActivityResult( -// ActivityResultContracts.StartActivityForResult() -// ) { result -> -// if (result.resultCode == Activity.RESULT_OK) { -// // Refresh order list when returning with OK result -//// loadOrders() -// } -// } - private fun navigateToOrderDetail(order: OrdersItem) { val intent = Intent(requireContext(), DetailOrderStatusActivity::class.java).apply { putExtra("ORDER_ID", order.orderId) @@ -239,11 +173,10 @@ class OrderListFragment : Fragment(), OrderHistoryAdapter.OrderActionCallbacks { detailOrderLauncher.launch(intent) } - - override fun onOrderCancelled(orderId: String, success: Boolean, message: String) { if (success) { - Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), "Berhasil batalkan pesanan", Toast.LENGTH_SHORT).show() + Log.d("OrderListFragment", "Order cancel success: $message") // loadOrders() // Refresh the list if (success) viewModel.updateStatus(status, forceRefresh = true) @@ -254,11 +187,13 @@ class OrderListFragment : Fragment(), OrderHistoryAdapter.OrderActionCallbacks { override fun onOrderCompleted(orderId: Int, success: Boolean, message: String) { if (success) { - Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), "Pesanan selesai", Toast.LENGTH_SHORT).show() + Log.d("OrderListFragment", "Pesanan selesai: $message") // loadOrders() // Refresh the list if (success) viewModel.updateStatus(status, forceRefresh = true) } else { - Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() + Log.e("OrderListFragment", "Error Order Complete: $message") + Toast.makeText(requireContext(), "Terdapat kendala di pesanan selesai", Toast.LENGTH_SHORT).show() } } @@ -271,20 +206,8 @@ class OrderListFragment : Fragment(), OrderHistoryAdapter.OrderActionCallbacks { _binding = null } -// private fun observeOrderCompletionStatus() { -// viewModel.orderCompletionStatus.observe(viewLifecycleOwner) { result -> -// when (result) { -// is Result.Loading -> { -// // Handle loading state if needed -// } -// is Result.Success -> { -// Toast.makeText(requireContext(), "Order completed successfully!", Toast.LENGTH_SHORT).show() -//// loadOrders() -// } -// is Result.Error -> { -// Toast.makeText(requireContext(), "Failed to complete order: ${result.exception.message}", Toast.LENGTH_SHORT).show() -// } -// } -// } -// } + override fun onResume() { + super.onResume() + observeOrderList() + } } \ No newline at end of file diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/MyStoreActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/MyStoreActivity.kt index 7df2ca9..b9aa908 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/MyStoreActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/MyStoreActivity.kt @@ -208,6 +208,9 @@ class MyStoreActivity : AppCompatActivity() { override fun onResume() { super.onResume() + lifecycleScope.launch { + viewModel.getAllStatusCounts() + } viewModel.loadMyStore() viewModel.loadMyStoreProducts() viewModel.fetchBalance() diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/profile/address/DetailStoreAddressActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/profile/address/DetailStoreAddressActivity.kt index 1e98b94..4a3b439 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/profile/address/DetailStoreAddressActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/profile/address/DetailStoreAddressActivity.kt @@ -322,19 +322,6 @@ class DetailStoreAddressActivity : AppCompatActivity() { villageId = oldAddress.villageId ) viewModel.saveStoreAddress(oldAddress, newAddress) - // Save address -// viewModel.saveStoreAddress( -// provinceId = selectedProvinceId!!, -// provinceName = province?.provinceName ?: "", -// cityId = city.cityId, -// cityName = city.cityName, -// street = street, -// subdistrict = subdistrict, -// detail = detail, -// postalCode = postalCode, -// latitude = latitude, -// longitude = longitude -// ) } } @@ -360,11 +347,13 @@ class DetailStoreAddressActivity : AppCompatActivity() { it.isEnabled = true it.setBackgroundResource(R.drawable.bg_button_active) it.setTextColor(getColor(R.color.white)) + binding.btnSaveAddress.text = "Simpan Perubahan" + } else { it.isEnabled = false it.setBackgroundResource(R.drawable.bg_button_disabled) it.setTextColor(getColor(R.color.black_300)) - Toast.makeText(this, "Periksa dan lenkapi alamat anda", Toast.LENGTH_SHORT).show() + binding.btnSaveAddress.text = "Lengkapi alamat anda" } } } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/SellsFragment.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/SellsFragment.kt index 2d5d2ac..baba53c 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/SellsFragment.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/SellsFragment.kt @@ -5,9 +5,15 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup 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.data.api.retrofit.ApiConfig +import com.alya.ecommerce_serang.data.repository.SellsRepository import com.alya.ecommerce_serang.databinding.FragmentSellsBinding +import com.alya.ecommerce_serang.utils.BaseViewModelFactory import com.alya.ecommerce_serang.utils.SessionManager +import com.alya.ecommerce_serang.utils.viewmodel.SellsViewModel import com.google.android.material.tabs.TabLayoutMediator class SellsFragment : Fragment() { @@ -18,6 +24,13 @@ class SellsFragment : Fragment() { private lateinit var viewPagerAdapter: SellsViewPagerAdapter + private val sellsVm: SellsViewModel by activityViewModels { + BaseViewModelFactory { + val api = ApiConfig.getApiService(SessionManager(requireContext())) + SellsViewModel(SellsRepository(api)) + } + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -53,8 +66,25 @@ class SellsFragment : Fragment() { else -> "Tab $position" } }.attach() + + statusPage() } + private fun statusPage(){ + binding.viewPagerSells.registerOnPageChangeCallback( + object : ViewPager2.OnPageChangeCallback() { + override fun onPageSelected(position: Int) { + val status = viewPagerAdapter.sellsStatuses[position] + sellsVm.updateStatus(status, forceRefresh = true) + } + } + ) + } + + override fun onResume() { + super.onResume() + statusPage() + } override fun onDestroyView() { super.onDestroyView() _binding = null diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/SellsListFragment.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/SellsListFragment.kt index bfc63cd..70fea0b 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/SellsListFragment.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/SellsListFragment.kt @@ -87,7 +87,6 @@ class SellsListFragment : Fragment() { setupRecyclerView() observeSellsList() observePaymentConfirmation() -// getAllOrderCountsAndNavigate() } private fun setupRecyclerView() { @@ -121,8 +120,8 @@ class SellsListFragment : Fragment() { Log.d(TAG, "Data received: ${result.data?.size ?: 0} items") if (result.data.isNullOrEmpty()) { - binding.tvEmptyState.visibility = View.VISIBLE binding.rvSells.visibility = View.GONE + binding.tvEmptyState.visibility = View.VISIBLE Log.d(TAG, "Showing empty state") } else { diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/SellsViewPagerAdapter.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/SellsViewPagerAdapter.kt index 90ff3d3..07df801 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/SellsViewPagerAdapter.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/SellsViewPagerAdapter.kt @@ -9,7 +9,7 @@ class SellsViewPagerAdapter( ) : FragmentStateAdapter(fragmentActivity) { // Define all possible sells statuses - keeping your original list - private val sellsStatuses = listOf( + val sellsStatuses = listOf( "all", "unpaid", "paid", diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/payment/DetailPaymentActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/payment/DetailPaymentActivity.kt index 4b6ca0f..f12bd42 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/payment/DetailPaymentActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/payment/DetailPaymentActivity.kt @@ -2,7 +2,6 @@ package com.alya.ecommerce_serang.ui.profile.mystore.sells.payment import android.app.Dialog import android.graphics.Color -import android.graphics.drawable.ColorDrawable import android.graphics.drawable.Drawable import android.os.Bundle import android.util.Log @@ -16,6 +15,8 @@ import android.widget.TextView import android.widget.Toast import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity +import androidx.core.graphics.drawable.toDrawable +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.response.store.sells.Orders @@ -38,9 +39,6 @@ import java.text.SimpleDateFormat import java.util.Calendar import java.util.Locale import java.util.TimeZone -import androidx.core.graphics.drawable.toDrawable -import androidx.recyclerview.widget.LinearLayoutManager -import com.alya.ecommerce_serang.ui.profile.mystore.sells.DetailSellsActivity class DetailPaymentActivity : AppCompatActivity() { @@ -139,6 +137,7 @@ class DetailPaymentActivity : AppCompatActivity() { tvOrderSubtotal.text = formatPrice(sell.totalAmount.toString()) tvOrderShipPrice.text = formatPrice(sell.shipmentPrice.toString()) tvOrderPrice.text = formatPrice(sell.totalAmount.toString()) + tvOrderDue.text = formatDueDate(sell.updatedAt.toString(), 2) tvOrderRecipient.text = sell.recipient ?: "-" tvOrderRecipientNum.text = sell.receiptNum?.toString() ?: "-" @@ -201,6 +200,28 @@ class DetailPaymentActivity : AppCompatActivity() { } } + private fun formatDueDate(dateString: String, dueDay: Int): String { + return try { + val inputFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault()) + inputFormat.timeZone = TimeZone.getTimeZone("UTC") + + val outputFormat = SimpleDateFormat("dd MMM; HH.mm", Locale("id", "ID")) + + val date = inputFormat.parse(dateString) + + date?.let { + val calendar = Calendar.getInstance() + calendar.time = it + calendar.add(Calendar.DATE, dueDay) + + outputFormat.format(calendar.time) + } ?: dateString + } catch (e: Exception) { + Log.e("DateFormatting", "Error formatting date: ${e.message}") + dateString + } + } + private fun formatPrice(price: String): String { val priceDouble = price.toDoubleOrNull() ?: 0.0 return String.format(Locale("id", "ID"), "Rp%,.0f", priceDouble) diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/shipment/DetailShipmentActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/shipment/DetailShipmentActivity.kt index 99b8077..d80b5b8 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/shipment/DetailShipmentActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/shipment/DetailShipmentActivity.kt @@ -14,7 +14,6 @@ import com.alya.ecommerce_serang.data.repository.AddressRepository import com.alya.ecommerce_serang.data.repository.SellsRepository import com.alya.ecommerce_serang.databinding.ActivityDetailShipmentBinding import com.alya.ecommerce_serang.ui.profile.mystore.sells.SellsProductAdapter -import com.alya.ecommerce_serang.ui.profile.mystore.sells.payment.DetailPaymentActivity import com.alya.ecommerce_serang.utils.BaseViewModelFactory import com.alya.ecommerce_serang.utils.SessionManager import com.alya.ecommerce_serang.utils.viewmodel.AddressViewModel @@ -24,7 +23,6 @@ import java.text.SimpleDateFormat import java.util.Calendar import java.util.Locale import java.util.TimeZone -import kotlin.getValue class DetailShipmentActivity : AppCompatActivity() { @@ -106,6 +104,7 @@ class DetailShipmentActivity : AppCompatActivity() { tvOrderSubtotal.text = formatPrice(sell.totalAmount.toString()) tvOrderShipPrice.text = formatPrice(sell.shipmentPrice.toString()) tvOrderPrice.text = formatPrice(sell.totalAmount.toString()) + tvOrderDue.text = formatDueDate(sell.updatedAt.toString(), 2) tvOrderRecipient.text = sell.recipient ?: "-" tvOrderRecipientNum.text = sell.receiptNum?.toString() ?: "-" @@ -168,6 +167,28 @@ class DetailShipmentActivity : AppCompatActivity() { } } + private fun formatDueDate(dateString: String, dueDay: Int): String { + return try { + val inputFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault()) + inputFormat.timeZone = TimeZone.getTimeZone("UTC") + + val outputFormat = SimpleDateFormat("dd MMM; HH.mm", Locale("id", "ID")) + + val date = inputFormat.parse(dateString) + + date?.let { + val calendar = Calendar.getInstance() + calendar.time = it + calendar.add(Calendar.DATE, dueDay) + + outputFormat.format(calendar.time) + } ?: dateString + } catch (e: Exception) { + Log.e("DateFormatting", "Error formatting date: ${e.message}") + dateString + } + } + private fun formatPrice(price: String): String { val priceDouble = price.toDoubleOrNull() ?: 0.0 return String.format(Locale("id", "ID"), "Rp%,.0f", priceDouble) diff --git a/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/SellsViewModel.kt b/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/SellsViewModel.kt index 05a26aa..6341637 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/SellsViewModel.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/SellsViewModel.kt @@ -17,6 +17,9 @@ import com.alya.ecommerce_serang.ui.order.address.ViewState import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch import java.text.SimpleDateFormat import java.util.Locale @@ -52,6 +55,9 @@ class SellsViewModel(private val repository: SellsRepository) : ViewModel() { private val _error = MutableLiveData() val error: LiveData get() = _error + private val _selectedStatus = MutableStateFlow("all") + val selectedStatus: StateFlow = _selectedStatus.asStateFlow() + fun getSellList(status: String) { Log.d(TAG, "========== Starting getSellList ==========") Log.d(TAG, "Requested status: '$status'") @@ -320,4 +326,40 @@ class SellsViewModel(private val repository: SellsRepository) : ViewModel() { Log.d(TAG, "========== refreshOrders method completed ==========") } + + 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()") + getAllStatusCounts() // network → cache + } else { + Log.d(TAG, "🌐 repository.getOrderList(\"$status\")") + repository.getSellList(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) + } + } } \ No newline at end of file diff --git a/app/src/main/res/drawable/logo_bisa_umkm.xml b/app/src/main/res/drawable/logo_bisa_umkm.xml new file mode 100644 index 0000000..85af4bf --- /dev/null +++ b/app/src/main/res/drawable/logo_bisa_umkm.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_detail_product.xml b/app/src/main/res/layout/activity_detail_product.xml index 5ee1000..d468627 100644 --- a/app/src/main/res/layout/activity_detail_product.xml +++ b/app/src/main/res/layout/activity_detail_product.xml @@ -14,7 +14,6 @@ android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> - @@ -219,7 +218,7 @@ android:layout_weight="1" android:text="@string/ulasan_pembeli" android:textColor="@color/black" - android:textSize="16sp" + android:textSize="14sp" android:textStyle="bold" /> + android:textSize="12sp" /> @@ -319,7 +318,7 @@ android:layout_weight="1" android:text="@string/stock_product" android:fontFamily="@font/dmsans_semibold" - android:textSize="14sp" /> + android:textSize="12sp" /> @@ -358,8 +357,8 @@ android:layout_height="wrap_content" android:text="@string/deskripsi_produk" android:textColor="@color/black" - android:textSize="16sp" - android:layout_marginTop="8dp" + android:textSize="14sp" + android:layout_marginTop="16dp" android:textStyle="bold" /> @@ -422,7 +421,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/black" - android:textSize="16sp" + android:textSize="14sp" android:textStyle="bold" tools:text="SnackEnak" /> @@ -430,8 +429,9 @@ android:id="@+id/tvSellerLocation" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:fontFamily="@font/dmsans_semibold" - android:textSize="14sp" + android:fontFamily="@font/dmsans_regular" + android:textColor="@color/black_300" + android:textSize="12sp" tools:text="Jakarta Selatan" /> @@ -484,7 +484,7 @@ android:layout_weight="1" android:text="@string/produk_lainnya" android:textColor="@color/black" - android:textSize="16sp" + android:textSize="14sp" android:textStyle="bold" /> diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 615340e..5c483cd 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -6,6 +6,8 @@ android:layout_height="match_parent" android:paddingHorizontal="32dp" android:paddingVertical="16dp" + android:layout_marginTop="32dp" + android:theme="@style/Theme.Ecommerce_serang" tools:context=".ui.auth.LoginActivity"> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 01343ed..acfa190 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -147,29 +147,112 @@ Mohon untuk melengkapi formulir pendaftaran ini agar dapat mengakses fitur penjual pada aplikasi. - + + Bank of America + Bank of China (Hong Kong) + Citibank + Deutsche Bank Ag + JP Morgan Chase Bank + MUFG Bank Allo Bank Indonesia - Bank Digital BCA - Bank Central Asia (BCA) + Bank Aceh Syariah + Bank Aladin Syariah + Bank Amar Indonesia + Bank ANZ Indonesia + Bank Artha Graha Internasional Bank BCA Syariah - Bank Jago - Bank Mandiri - Bank Kb Bukopi + Bank BNP Paribas Indonesia + Bank BTPN Syariah + Bank Bumi Arta + Bank Capital Indonesia + Bank Central Asia (BCA) + Bank China Construction Bank Indonesia + Bank CIMB Niaga + Bank CTBC Indonesia + Bank Danamon Indonesia + Bank DBS Indonesia + Bank Digital BCA + Bank Ganesha + Bank Hibank Indonesia + Bank HSBC Indonesia + Bank IBK Indonesia + Bank ICBC Indonesia + Bank Ina Perdana + Bank Index Selindo Bank Jabar Banten Syariah - Bank Mandiri Taspen - Bank Maybank Indonesia + Bank Jago + Bank JTrust Indonesia + Bank Kb Bukopin Syariah + Bank Kb Bukopin + Bank Keb Hana Indonesia + Bank Mandiri + Bank Mandiri Taspen + Bank Maspion Indonesia + Bank Mayapada International + Bank Maybank Indonesia + Bank Mega Syariah + Bank Mega + Bank Mestika Dharma + Bank Mizuho Indonesia + Bank MNC Internasional + Bank Muamalat Indonesia + Bank Multiarta Sentosa + Bank Nagari + Bank Nano Syariah + Bank Nationalnobu Bank Negara Indonesia (BNI) + Bank Neo Commerce + Bank NTB Syariah + Bank OCBC NISP + Bank of India Indonesia + Bank Oke Indonesia + Bank PAN Indonesia + Bank Panin Dubai Syariah + Bank Pembangunan Daerah (BPD) Bali Bank Permata + Bank QNB Indonesia Bank Rakyat Indonesia (BRI) + Bank Raya Indonesia + Bank Resona Perdania + Bank Sahabat Sampoerna Bank Saqu Indonesia + Bank SBI Indonesia Bank Seabank Indonesia - Bank Sinarmas + Bank Shinhan Indonesia + Bank Sinarmas + Bank SMBC Indonesia Bank Syariah Indonesia (BSI) Bank Tabungan Negara (BTN) Bank UOB Indonesia + Bank Victoria International + Bank Victoria Syariah + Bank Woori Saudara Indonesia 1906 + BPD Banten + BPD Bengkulu + BPD Daerah Istimewa Yogyakarta + BPD DKI + BPD Jambi BPD Jawa Barat dan Banten + BPD Jawa Tengah + BPD Jawa Timur + BPD Kalimantan Barat + BPD Kalimantan Selatan + BPD Kalimantan Tengah + BPD Kalimantan Timur dan Kalimantan Utara + BPD Lampung + BPD Maluku dan Maluku Utara + BPD Nusa Tenggara Timur + BPD Papua + BPD Riau Kepri Syariah + BPD Sulawesi Selatan dan Sulawesi Barat + BPD Sulawesi Tengah + BPD Sulawesi Tenggara + BPD Sulawesi Utara dan Gorontalo + BPD Sumatera Selatan dan Bangka Belitung + BPD Sumatera Utara + Krom Bank Indonesia Super Bank Indonesia - + Standard Chartered Bank \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 6ec5b1b..6c1b3e1 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -1,4 +1,4 @@ - + - + \ No newline at end of file