sells and address

This commit is contained in:
Gracia Hotmauli
2025-08-30 06:49:55 +07:00
parent 593231285a
commit 7f4d04ac7a
9 changed files with 193 additions and 27 deletions

View File

@ -34,6 +34,7 @@ import com.alya.ecommerce_serang.data.repository.UserRepository
import com.alya.ecommerce_serang.databinding.ActivityAddAddressBinding
import com.alya.ecommerce_serang.utils.SavedStateViewModelFactory
import com.alya.ecommerce_serang.utils.SessionManager
import com.alya.ecommerce_serang.utils.applyLiveCounter
class AddAddressActivity : AppCompatActivity() {
private lateinit var binding: ActivityAddAddressBinding
@ -65,6 +66,12 @@ class AddAddressActivity : AppCompatActivity() {
binding = ActivityAddAddressBinding.inflate(layoutInflater)
setContentView(binding.root)
applyLiveCounter(
binding.etDetailAlamat,
binding.tvCountDetail,
binding.tvCountDetailMax
)
sessionManager = SessionManager(this)
apiService = ApiConfig.getApiService(sessionManager)
locationManager = getSystemService(LOCATION_SERVICE) as LocationManager

View File

@ -106,22 +106,23 @@ class MyStoreActivity : AppCompatActivity() {
}
binding.tvHistory.setOnClickListener {
startActivity(Intent(this, SellsActivity::class.java))
//startActivity(Intent(this, SellsActivity::class.java))
startSellsActivityWithStatus("all")
}
binding.layoutPerluTagihan.setOnClickListener {
startActivity(Intent(this, SellsActivity::class.java))
//navigateToSellsFragment("pending")
//startActivity(Intent(this, SellsActivity::class.java))
startSellsActivityWithStatus("unpaid")
}
binding.layoutPembayaran.setOnClickListener {
startActivity(Intent(this, SellsActivity::class.java))
//navigateToSellsFragment("paid")
//startActivity(Intent(this, SellsActivity::class.java))
startSellsActivityWithStatus("paid")
}
binding.layoutPerluDikirim.setOnClickListener {
startActivity(Intent(this, SellsActivity::class.java))
//navigateToSellsFragment("processed")
//startActivity(Intent(this, SellsActivity::class.java))
startSellsActivityWithStatus("processed")
}
binding.layoutProductMenu.setOnClickListener {
@ -205,6 +206,12 @@ class MyStoreActivity : AppCompatActivity() {
}
}
private fun startSellsActivityWithStatus(status: String?) {
val intent = Intent(this, SellsActivity::class.java)
intent.putExtra(SellsActivity.EXTRA_INITIAL_STATUS, status)
startActivity(intent)
}
override fun onResume() {
super.onResume()
lifecycleScope.launch {

View File

@ -8,6 +8,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.widget.doAfterTextChanged
import androidx.fragment.app.commit
import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
@ -18,6 +19,9 @@ import com.alya.ecommerce_serang.utils.SessionManager
import com.alya.ecommerce_serang.utils.viewmodel.SellsViewModel
class SellsActivity : AppCompatActivity() {
companion object {
const val EXTRA_INITIAL_STATUS = "extra_initial_status"
}
private lateinit var binding: ActivitySellsBinding
private lateinit var sessionManager: SessionManager
@ -68,11 +72,18 @@ class SellsActivity : AppCompatActivity() {
onBackPressed()
finish()
}
// binding.edtSearch.doAfterTextChanged {
// val q = it?.toString()?.trim().orEmpty()
// (supportFragmentManager.findFragmentById(R.id.fragment_container_sells) as? SellsFragment)
// ?.onSearchQueryChanged(q)
// }
}
private fun showSellsFragment() {
val initialStatus = intent.getStringExtra(EXTRA_INITIAL_STATUS)
supportFragmentManager.commit {
replace(R.id.fragment_container_sells, SellsFragment())
replace(R.id.fragment_container_sells, SellsFragment.newInstance(initialStatus))
}
}
}

View File

@ -17,8 +17,19 @@ import com.alya.ecommerce_serang.utils.viewmodel.SellsViewModel
import com.google.android.material.tabs.TabLayoutMediator
class SellsFragment : Fragment() {
companion object {
private const val ARG_INITIAL_STATUS = "arg_initial_status"
fun newInstance(initialStatus: String?): SellsFragment =
SellsFragment().apply {
arguments = Bundle().apply {
putString(ARG_INITIAL_STATUS, initialStatus)
}
}
}
private var _binding: FragmentSellsBinding? = null
// private var currentSearchQuery = ""
private val binding get() = _binding!!
private lateinit var sessionManager: SessionManager
@ -45,6 +56,8 @@ class SellsFragment : Fragment() {
sessionManager = SessionManager(requireContext())
setupViewPager()
jumpToInitialStatusIfAny()
// binding.viewPagerSells.post { currentPage()?.filter(currentSearchQuery) }
}
private fun setupViewPager() {
@ -70,12 +83,60 @@ class SellsFragment : Fragment() {
statusPage()
}
private fun statusPage(){
private fun jumpToInitialStatusIfAny() {
val initial = arguments?.getString(ARG_INITIAL_STATUS)?.trim().orEmpty()
if (initial.isEmpty()) return
// Try adapters list first
var index = viewPagerAdapter.sellsStatuses.indexOf(initial)
// Fallback mapping (keeps working if the adapter changes order names)
if (index < 0) {
index = when (initial) {
"all" -> 0
"unpaid" -> 1
"paid" -> 2
"processed" -> 3
"shipped" -> 4
"delivered" -> 5
"completed" -> 6
"canceled" -> 7
else -> 0
}
}
if (index in 0 until (binding.viewPagerSells.adapter?.itemCount ?: 0)) {
// Ensure pager is ready, then jump without animation
binding.viewPagerSells.post {
binding.viewPagerSells.setCurrentItem(index, false)
// Make sure ViewModel filter matches the shown tab
sellsVm.updateStatus(
viewPagerAdapter.sellsStatuses.getOrNull(index) ?: initial,
forceRefresh = true
)
}
}
}
// fun onSearchQueryChanged(q: String) {
// currentSearchQuery = q
// currentPage()?.filter(q)
// }
// private fun currentPage(): SellsListFragment? {
// val pos = binding.viewPagerSells.currentItem
// val tag = "f${viewPagerAdapter.getItemId(pos)}" // requires stable ids in adapter (see step 4)
// return childFragmentManager.findFragmentByTag(tag) as? SellsListFragment
// }
private fun statusPage() {
binding.viewPagerSells.registerOnPageChangeCallback(
object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
val status = viewPagerAdapter.sellsStatuses[position]
sellsVm.updateStatus(status, forceRefresh = true)
// re-apply query when user switches tab
// currentPage()?.filter(currentSearchQuery)
}
}
)

View File

@ -25,6 +25,7 @@ import com.alya.ecommerce_serang.utils.SessionManager
import com.alya.ecommerce_serang.utils.viewmodel.SellsViewModel
import com.google.gson.Gson
import kotlinx.coroutines.launch
import java.util.Locale
class SellsListFragment : Fragment() {
@ -41,6 +42,13 @@ class SellsListFragment : Fragment() {
}
private lateinit var sellsAdapter: SellsAdapter
private var status: String = "all"
// private var allOrders: List<OrdersItem> = emptyList()
// private var currentQuery: String = ""
//
// fun filter(query: String) {
// currentQuery = query
// applyFilter()
// }
companion object {
private const val TAG = "SellsListFragment"
@ -89,6 +97,29 @@ class SellsListFragment : Fragment() {
observePaymentConfirmation()
}
// private fun applyFilter() {
// val q = currentQuery.lowercase(Locale.getDefault())
// val filtered = if (q.isBlank()) {
// allOrders
// } else {
// allOrders.filter { it.matches(q) }
// }
//
// sellsAdapter.submitList(filtered)
// binding.tvEmptyState.visibility = if (filtered.isEmpty()) View.VISIBLE else View.GONE
// binding.rvSells.visibility = if (filtered.isEmpty()) View.GONE else View.VISIBLE
// }
//
// private fun OrdersItem.matches(q: String): Boolean {
// val id = orderId?.toString()?.lowercase(Locale.getDefault()) ?: ""
// val customer = username?.lowercase(Locale.getDefault()) ?: ""
// val location = subdistrict?.lowercase(Locale.getDefault()) ?: ""
// val productHit = orderItems?.any { it?.productName
// ?.lowercase(Locale.getDefault())?.contains(q) == true } == true
//
// return id.contains(q) || customer.contains(q) || location.contains(q) || productHit
// }
private fun setupRecyclerView() {
Log.d(TAG, "Setting up RecyclerView")
sellsAdapter = SellsAdapter(
@ -118,6 +149,8 @@ class SellsListFragment : Fragment() {
is ViewState.Success -> {
binding.progressBar.visibility = View.GONE
Log.d(TAG, "Data received: ${result.data?.size ?: 0} items")
// allOrders = result.data ?: emptyList()
// applyFilter() // ← apply current query to fresh data
if (result.data.isNullOrEmpty()) {
binding.rvSells.visibility = View.GONE
@ -135,7 +168,8 @@ class SellsListFragment : Fragment() {
sellsAdapter.submitList(result.data)
Log.d(TAG, "Data submitted to adapter")
Log.d(TAG, "Adapter item count: ${sellsAdapter.itemCount}") }
Log.d(TAG, "Adapter item count: ${sellsAdapter.itemCount}")
}
}
is ViewState.Error -> {
Log.e(TAG, "❌ ViewState.Error received: ${result.message}")
@ -144,9 +178,7 @@ class SellsListFragment : Fragment() {
binding.tvEmptyState.visibility = View.VISIBLE
// Toast.makeText(requireContext(), result.message, Toast.LENGTH_SHORT).show()
}
is ViewState.Loading -> {
binding.progressBar.visibility = View.VISIBLE
}
is ViewState.Loading -> binding.progressBar.visibility = View.VISIBLE
}
}
}
@ -213,7 +245,7 @@ class SellsListFragment : Fragment() {
override fun onResume() {
super.onResume()
viewModel.getSellList(status)
observeSellsList()
//observeSellsList()
}
override fun onDestroyView() {

View File

@ -26,4 +26,7 @@ class SellsViewPagerAdapter(
// Create a new instance of SellsListFragment with the appropriate status
return SellsListFragment.newInstance(sellsStatuses[position])
}
// override fun getItemId(position: Int): Long = sellsStatuses[position].hashCode().toLong()
// override fun containsItem(itemId: Long): Boolean =
// sellsStatuses.any { it.hashCode().toLong() == itemId }
}

View File

@ -85,14 +85,45 @@
android:id="@+id/etDetailAlamat"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:background="@drawable/edit_text_background"
android:gravity="top"
android:hint="Isi detail alamat (nomor rumah, lantai, dll)"
android:inputType="textMultiLine"
android:lines="3"
android:padding="12dp"
android:textSize="14sp" />
android:background="@drawable/bg_text_field"
android:padding="8dp"
style="@style/body_small"
android:hint="Isi detail alamat di sini, contoh: Blok, No. Kavling, dsb."
android:layout_marginTop="10dp"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="end"
android:layout_marginTop="4dp">
<TextView
android:id="@+id/tv_count_detail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/label_small"
android:text="0"
android:layout_marginEnd="2dp"
android:textColor="@color/black_300"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/label_small"
android:text="/"
android:layout_marginEnd="2dp"
android:textColor="@color/black_300"/>
<TextView
android:id="@+id/tv_count_detail_max"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/label_small"
android:text="100"
android:textColor="@color/black_300"/>
</LinearLayout>
<!-- Provinsi -->
<TextView
@ -200,7 +231,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Desa"
android:text="Desa / Kelurahan"
android:textColor="@android:color/black"
android:textSize="14sp" />
<com.google.android.material.textfield.TextInputLayout

View File

@ -17,7 +17,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:background="@color/white">
android:background="@color/white"
android:visibility="gone">
<LinearLayout
android:layout_width="match_parent"