diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5e89a06..f7e9e77 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -29,6 +29,9 @@ android:theme="@style/Theme.Ecommerce_serang" android:usesCleartextTraffic="true" tools:targetApi="31"> + 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 0965a96..8f270a5 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 @@ -26,6 +26,7 @@ import com.alya.ecommerce_serang.ui.cart.CartActivity import com.alya.ecommerce_serang.ui.notif.NotificationActivity import com.alya.ecommerce_serang.ui.product.DetailProductActivity import com.alya.ecommerce_serang.ui.product.category.CategoryProductsActivity +import com.alya.ecommerce_serang.ui.product.listproduct.ListCategoryActivity import com.alya.ecommerce_serang.ui.product.listproduct.ListProductActivity import com.alya.ecommerce_serang.utils.BaseViewModelFactory import com.alya.ecommerce_serang.utils.SessionManager @@ -100,6 +101,11 @@ class HomeFragment : Fragment() { val intent = Intent(requireContext(), ListProductActivity::class.java) startActivity(intent) } + + binding.categoryShowAll.setOnClickListener { + val intent = Intent(requireContext(), ListCategoryActivity::class.java) + startActivity(intent) + } } private fun setupSearchView() { diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/CheckoutActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/CheckoutActivity.kt index f7859e4..9f4e7e4 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/CheckoutActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/CheckoutActivity.kt @@ -326,10 +326,10 @@ class CheckoutActivity : AppCompatActivity() { } } - // Voucher section (if implemented) - binding.layoutVoucher?.setOnClickListener { - Toast.makeText(this, "Voucher feature not implemented", Toast.LENGTH_SHORT).show() - } +// // Voucher section (if implemented) +// binding.layoutVoucher?.setOnClickListener { +// Toast.makeText(this, "Voucher feature not implemented", Toast.LENGTH_SHORT).show() +// } } private val addressSelectionLauncher = registerForActivityResult( diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/product/DetailProductActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/product/DetailProductActivity.kt index 81fee0e..9630784 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/product/DetailProductActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/product/DetailProductActivity.kt @@ -360,6 +360,8 @@ class DetailProductActivity : AppCompatActivity() { val btnClose = view.findViewById(R.id.btnCloseDialog) val switchWholesale = view.findViewById(R.id.switch_price) + val titleWholesale = view.findViewById(R.id.tv_active_wholesale) +// val descWholesale = view.findViewById(R.id.tv_desc_wholesale) if (!isBuyNow) { btnBuyNow.setText(R.string.add_to_cart) @@ -368,10 +370,18 @@ class DetailProductActivity : AppCompatActivity() { switchWholesale.isEnabled = isWholesaleAvailable switchWholesale.isChecked = isWholesaleSelected - // Set initial quantity based on current selection currentQuantity = if (isWholesaleSelected) minOrder else 1 tvQuantity.text = currentQuantity.toString() + if (isWholesaleAvailable){ + switchWholesale.visibility = View.VISIBLE + Toast.makeText(this, "Minimal pembelian grosir $currentQuantity produk", Toast.LENGTH_SHORT).show() + } else { + switchWholesale.visibility = View.GONE + } + // Set initial quantity based on current selection + + switchWholesale.setOnCheckedChangeListener { _, isChecked -> isWholesaleSelected = isChecked diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/product/listproduct/ListCategoryActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/product/listproduct/ListCategoryActivity.kt new file mode 100644 index 0000000..73f20fd --- /dev/null +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/product/listproduct/ListCategoryActivity.kt @@ -0,0 +1,112 @@ +package com.alya.ecommerce_serang.ui.product.listproduct + +import android.content.Intent +import android.os.Bundle +import android.util.Log +import android.view.View +import androidx.activity.enableEdgeToEdge +import androidx.activity.viewModels +import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.ViewCompat +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsCompat +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.alya.ecommerce_serang.data.api.dto.CategoryItem +import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig +import com.alya.ecommerce_serang.data.repository.ProductRepository +import com.alya.ecommerce_serang.databinding.ActivityListCategoryBinding +import com.alya.ecommerce_serang.ui.product.category.CategoryProductsActivity +import com.alya.ecommerce_serang.utils.BaseViewModelFactory +import com.alya.ecommerce_serang.utils.SessionManager +import com.alya.ecommerce_serang.utils.viewmodel.HomeViewModel + +class ListCategoryActivity : AppCompatActivity() { + companion object { + private val TAG = "ListCategoryActivity" + } + private lateinit var binding: ActivityListCategoryBinding + private lateinit var sessionManager: SessionManager + private var categoryAdapter: ListCategoryAdapter? = null + + private val viewModel: HomeViewModel by viewModels { + BaseViewModelFactory { + val apiService = ApiConfig.getApiService(sessionManager) + val repository = ProductRepository(apiService) + HomeViewModel(repository) + } + } + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityListCategoryBinding.inflate(layoutInflater) + setContentView(binding.root) + + sessionManager = SessionManager(this) + + 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 + } + + setupToolbar() + setupObserver() + viewModel.loadCategory() + setupRecyclerView() + + } + + private fun setupToolbar(){ + binding.header.headerLeftIcon.setOnClickListener{ + finish() + } + binding.header.headerTitle.text = "Kategori Produk" + } + + private fun setupRecyclerView(){ + categoryAdapter = ListCategoryAdapter( + categories = emptyList(), + onClick = { category -> handleClickOnCategory(category) } + ) + + binding.rvListCategories.apply { + adapter = categoryAdapter + layoutManager = GridLayoutManager( + context, + 3, // 3 columns + RecyclerView.VERTICAL, + false + ) + } + } + + private fun setupObserver(){ + viewModel.category.observe(this) { category -> + Log.d("ListCategoryActivity", "Received categories: ${category.size}") + updateCategories(category) + } + } + + private fun updateCategories(category: List){ + if (category.isEmpty()) { + binding.rvListCategories.visibility = View.GONE + } else { + binding.rvListCategories.visibility = View.VISIBLE + categoryAdapter?.updateData(category) + } + } + + private fun handleClickOnCategory(category: CategoryItem){ + val intent = Intent(this, CategoryProductsActivity::class.java) + intent.putExtra(CategoryProductsActivity.EXTRA_CATEGORY, category) + startActivity(intent) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/product/listproduct/ListCategoryAdapter.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/product/listproduct/ListCategoryAdapter.kt new file mode 100644 index 0000000..d5fa5af --- /dev/null +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/product/listproduct/ListCategoryAdapter.kt @@ -0,0 +1,55 @@ +package com.alya.ecommerce_serang.ui.product.listproduct + +import android.util.Log +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.alya.ecommerce_serang.BuildConfig.BASE_URL +import com.alya.ecommerce_serang.R +import com.alya.ecommerce_serang.data.api.dto.CategoryItem +import com.alya.ecommerce_serang.databinding.ItemCategoryHomeBinding +import com.bumptech.glide.Glide + +class ListCategoryAdapter( + private var categories:List, + private val onClick:(category: CategoryItem) -> Unit +): RecyclerView.Adapter() { + + inner class ViewHolder(private val binding: ItemCategoryHomeBinding): RecyclerView.ViewHolder(binding.root){ + fun bind(category: CategoryItem) = with(binding) { + Log.d("CategoriesAdapter", "Binding category: ${category.name}, Image: ${category.image}") + + val fullImageUrl = if (category.image.startsWith("/")) { + BASE_URL + category.image.removePrefix("/") // Append base URL if the path starts with "/" + } else { + category.image // Use as is if it's already a full URL + } + + Log.d("CategoriesAdapter", "Loading image: $fullImageUrl") + + Glide.with(itemView.context) + .load(fullImageUrl) // Ensure full URL + .placeholder(R.drawable.placeholder_image) + .into(imageCategory) + + name.text = category.name + + root.setOnClickListener { onClick(category) } + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder ( + ItemCategoryHomeBinding.inflate(LayoutInflater.from(parent.context),parent,false) + ) + + override fun getItemCount() = categories.size + + override fun onBindViewHolder(holder: ListCategoryAdapter.ViewHolder, position: Int) { + holder.bind(categories[position]) + } + + fun updateData(newCategories: List) { + categories = newCategories.toList() + notifyDataSetChanged() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/product/listproduct/ListProductActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/product/listproduct/ListProductActivity.kt index 6a00f2e..2b74409 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/product/listproduct/ListProductActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/product/listproduct/ListProductActivity.kt @@ -69,7 +69,7 @@ class ListProductActivity : AppCompatActivity() { private fun setupRecyclerView() { - binding.rvProducts.apply { + binding.rvProductsList.apply { adapter = productAdapter layoutManager = GridLayoutManager( context, @@ -112,14 +112,14 @@ class ListProductActivity : AppCompatActivity() { private fun updateProducts(products: List, storeMap: Map) { if (products.isEmpty()) { Log.d(TAG, "Product list is empty, hiding RecyclerView") - binding.rvProducts.visibility = View.VISIBLE + binding.rvProductsList.visibility = View.VISIBLE } else { Log.d(TAG, "Displaying product list in RecyclerView") - binding.rvProducts.visibility = View.VISIBLE // <-- Fix here + binding.rvProductsList.visibility = View.VISIBLE // <-- Fix here productAdapter = ListProductAdapter(products, onClick = { product -> handleProductClick(product) }, storeMap = storeMap) - binding.rvProducts.adapter = productAdapter + binding.rvProductsList.adapter = productAdapter productAdapter?.updateProducts(products) } } diff --git a/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/HomeViewModel.kt b/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/HomeViewModel.kt index a7667cf..b37ad1b 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/HomeViewModel.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/HomeViewModel.kt @@ -1,6 +1,8 @@ package com.alya.ecommerce_serang.utils.viewmodel import android.util.Log +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.alya.ecommerce_serang.data.api.dto.CategoryItem @@ -25,6 +27,9 @@ class HomeViewModel ( private val _storeMap = MutableStateFlow>(emptyMap()) val storeMap: StateFlow> = _storeMap.asStateFlow() + private val _category = MutableLiveData>() + val category: LiveData> get() = _category + init { loadProducts() loadCategories() @@ -73,6 +78,16 @@ class HomeViewModel ( } } + fun loadCategory() { + viewModelScope.launch { + when (val result = productRepository.getAllCategories()) { + is Result.Success -> _category.value = result.data + is Result.Error -> Log.e("HomeViewModel", "Failed to fetch categories", result.exception) + is Result.Loading -> {} + } + } + } + fun retry() { loadProducts() diff --git a/app/src/main/res/layout/activity_checkout.xml b/app/src/main/res/layout/activity_checkout.xml index 8c793d4..2c5a7ba 100644 --- a/app/src/main/res/layout/activity_checkout.xml +++ b/app/src/main/res/layout/activity_checkout.xml @@ -142,35 +142,6 @@ android:layout_height="8dp" android:background="#F5F5F5" /> - - - - - - - - - - - - - + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_list_product.xml b/app/src/main/res/layout/activity_list_product.xml index ebf3300..aab4e4c 100644 --- a/app/src/main/res/layout/activity_list_product.xml +++ b/app/src/main/res/layout/activity_list_product.xml @@ -8,12 +8,14 @@ tools:context=".ui.product.listproduct.ListProductActivity"> + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintBottom_toTopOf="@id/rvProductsList"/> @@ -23,11 +25,11 @@ - + + + + + + + + +