update ui and detail store

This commit is contained in:
shaulascr
2025-05-22 04:17:55 +07:00
parent 419eddee90
commit e7fbace532
36 changed files with 819 additions and 116 deletions

View File

@ -29,6 +29,9 @@
android:theme="@style/Theme.Ecommerce_serang"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".ui.product.storeDetail.StoreDetailActivity"
android:exported="false" />
<activity
android:name=".ui.auth.RegisterStoreActivity"
android:exported="false" />
@ -67,6 +70,7 @@
android:enabled="true"
android:exported="false"
android:foregroundServiceType="dataSync" />
<activity
android:name=".ui.profile.mystore.profile.shipping_service.ShippingServiceActivity"
android:exported="false" />

View File

@ -5,7 +5,7 @@ import com.google.gson.annotations.SerializedName
data class OrderListResponse(
@field:SerializedName("orders")
val orders: List<OrdersItem?>? = null,
val orders: List<OrdersItem>,
@field:SerializedName("message")
val message: String? = null

View File

@ -314,7 +314,7 @@ interface ApiService {
suspend fun getListProv(
): Response<ListProvinceResponse>
@GET("order/{status}")
@GET("mystore/orders/{status}")
suspend fun getSellList(
@Path("status") status: String
): Response<com.alya.ecommerce_serang.data.api.response.store.orders.OrderListResponse>

View File

@ -6,15 +6,14 @@ import com.alya.ecommerce_serang.data.api.dto.CategoryItem
import com.alya.ecommerce_serang.data.api.dto.Preorder
import com.alya.ecommerce_serang.data.api.dto.ProductsItem
import com.alya.ecommerce_serang.data.api.dto.SearchRequest
import com.alya.ecommerce_serang.data.api.response.store.product.CreateProductResponse
import com.alya.ecommerce_serang.data.api.response.customer.cart.AddCartResponse
import com.alya.ecommerce_serang.data.api.response.customer.product.ProductResponse
import com.alya.ecommerce_serang.data.api.response.customer.product.ReviewsItem
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreProduct
import com.alya.ecommerce_serang.data.api.response.store.product.UpdateProductResponse
import com.alya.ecommerce_serang.data.api.response.product.Search
import com.alya.ecommerce_serang.data.api.response.store.product.CreateProductResponse
import com.alya.ecommerce_serang.data.api.response.store.product.UpdateProductResponse
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
import com.alya.ecommerce_serang.utils.SessionManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.MediaType.Companion.toMediaTypeOrNull
@ -119,7 +118,7 @@ class ProductRepository(private val apiService: ApiService) {
}
}
suspend fun fetchStoreDetail(storeId: Int): Result<StoreProduct?> {
suspend fun fetchStoreDetail(storeId: Int): Result<StoreProduct> {
return try {
val response = apiService.getDetailStore(storeId)
if (response.isSuccessful) {

View File

@ -8,6 +8,9 @@ import android.widget.Toast
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 com.alya.ecommerce_serang.data.api.dto.FcmReq
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
import com.alya.ecommerce_serang.data.repository.Result
@ -35,11 +38,30 @@ class LoginActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
binding = ActivityLoginBinding.inflate(layoutInflater)
setContentView(binding.root)
WindowCompat.setDecorFitsSystemWindows(window, false)
enableEdgeToEdge()
// Apply insets to your root layout
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()
@ -59,6 +81,11 @@ class LoginActivity : AppCompatActivity() {
loginViewModel.login(email, password)
}
}
binding.tvRegistrasi.setOnClickListener{
startActivity(Intent(this, RegisterActivity::class.java))
finish()
}
}
private fun observeLoginState() {

View File

@ -42,6 +42,23 @@ class RegisterActivity : AppCompatActivity() {
binding = ActivityRegisterBinding.inflate(layoutInflater)
setContentView(binding.root)
sessionManager = SessionManager(this)
WindowCompat.setDecorFitsSystemWindows(window, false)
enableEdgeToEdge()
// Apply insets to your root layout
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
val systemBars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
view.setPadding(
systemBars.left,
systemBars.top,
systemBars.right,
systemBars.bottom
)
windowInsets
}
Log.d("RegisterActivity", "Token in storage: '${sessionManager.getToken()}'")
Log.d("RegisterActivity", "User ID in storage: '${sessionManager.getUserId()}'")

View File

@ -63,22 +63,17 @@ class RegisterStoreActivity : AppCompatActivity() {
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d(TAG, "onCreate: Starting RegisterStoreActivity")
binding = ActivityRegisterStoreBinding.inflate(layoutInflater)
setContentView(binding.root)
sessionManager = SessionManager(this)
Log.d(TAG, "onCreate: SessionManager initialized")
WindowCompat.setDecorFitsSystemWindows(window, false)
Log.d(TAG, "onCreate: Window decoration set")
enableEdgeToEdge()
Log.d(TAG, "onCreate: Edge-to-edge enabled")
// Apply insets to your root layout
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
Log.d(TAG, "onCreate: Applying window insets")
val systemBars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
view.setPadding(
systemBars.left,

View File

@ -64,9 +64,9 @@ class RegisterStep1Fragment : Fragment() {
// Set step progress and description
(activity as? RegisterActivity)?.let {
it.findViewById<LinearProgressIndicator>(R.id.registration_progress)?.progress = 33
it.findViewById<TextView>(R.id.tv_step_title)?.text = "Step 1: Account & Personal Info"
it.findViewById<TextView>(R.id.tv_step_title)?.text = "Step 1: Informasi Akun"
it.findViewById<TextView>(R.id.tv_step_description)?.text =
"Fill in your account and personal details to create your profile."
"Masukkan data pengguna dengan data yang valid."
}
setupFieldValidations()

View File

@ -70,9 +70,9 @@ class RegisterStep2Fragment : Fragment() {
// Set step progress and description
(activity as? RegisterActivity)?.let {
it.findViewById<LinearProgressIndicator>(R.id.registration_progress)?.progress = 66
it.findViewById<TextView>(R.id.tv_step_title)?.text = "Step 2: Verify Your Email"
it.findViewById<TextView>(R.id.tv_step_title)?.text = "Step 2: Masukkan Kode OTP"
it.findViewById<TextView>(R.id.tv_step_description)?.text =
"Enter the verification code sent to your email to continue."
"Cek email untuk melihat kode OTP. Pastikan email yang digunakan aktif."
Log.d(TAG, "Step indicators updated to Step 2")
}

View File

@ -70,10 +70,10 @@ class RegisterStep3Fragment : Fragment() {
// Set step progress and description
(activity as? RegisterActivity)?.let {
it.findViewById<LinearProgressIndicator>(R.id.registration_progress)?.progress = 33
it.findViewById<TextView>(R.id.tv_step_title)?.text = "Step 1: Account & Personal Info"
it.findViewById<LinearProgressIndicator>(R.id.registration_progress)?.progress = 100
it.findViewById<TextView>(R.id.tv_step_title)?.text = "Step 3: Tambahkan Alamat"
it.findViewById<TextView>(R.id.tv_step_description)?.text =
"Fill in your account and personal details to create your profile."
"Masukkan alamat untuk menerima pesanan."
Log.d(TAG, "Step indicators updated to Step 1")
}

View File

@ -60,12 +60,20 @@ class CartActivity : AppCompatActivity() {
windowInsets
}
setupToolbar()
setupRecyclerView()
setupListeners()
observeViewModel()
viewModel.getCart()
}
private fun setupToolbar(){
binding.header.headerLeftIcon.setOnClickListener{
finish()
}
binding.header.headerTitle.text = "Keranjang"
}
private fun setupRecyclerView() {
storeAdapter = StoreAdapter(
onStoreCheckChanged = { storeId, isChecked ->

View File

@ -59,11 +59,6 @@ class ChatActivity : AppCompatActivity() {
// For image attachment
private var tempImageUri: Uri? = null
// // Chat parameters from intent
// private var chatRoomId: Int = 0
// private var storeId: Int = 0
// private var productId: Int = 0
// Typing indicator handler
private val typingHandler = android.os.Handler(android.os.Looper.getMainLooper())
private val stopTypingRunnable = Runnable {

View File

@ -3,8 +3,12 @@ package com.alya.ecommerce_serang.ui.notif
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.LinearLayoutManager
import com.alya.ecommerce_serang.data.repository.Result
import com.alya.ecommerce_serang.databinding.ActivityNotificationBinding
@ -30,6 +34,22 @@ class NotificationActivity : AppCompatActivity() {
binding = ActivityNotificationBinding.inflate(layoutInflater)
setContentView(binding.root)
WindowCompat.setDecorFitsSystemWindows(window, false)
enableEdgeToEdge()
// Apply insets to your root layout
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()
setupAdapters()
setupTabLayout()

View File

@ -5,8 +5,12 @@ import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
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.LinearLayoutManager
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
import com.alya.ecommerce_serang.data.repository.OrderRepository
@ -37,6 +41,22 @@ class ShippingActivity : AppCompatActivity() {
// Initialize SessionManager
sessionManager = SessionManager(this)
WindowCompat.setDecorFitsSystemWindows(window, false)
enableEdgeToEdge()
// Apply insets to your root layout
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
val systemBars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
view.setPadding(
systemBars.left,
systemBars.top,
systemBars.right,
systemBars.bottom
)
windowInsets
}
// Get data from intent
val addressId = intent.getIntExtra(EXTRA_ADDRESS_ID, 0)
val productId = intent.getIntExtra(EXTRA_PRODUCT_ID, 0)

View File

@ -13,10 +13,14 @@ import android.provider.Settings
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import com.alya.ecommerce_serang.data.api.dto.CreateAddressRequest
import com.alya.ecommerce_serang.data.api.dto.UserProfile
import com.alya.ecommerce_serang.data.api.response.customer.order.CitiesItem
@ -61,6 +65,22 @@ class AddAddressActivity : AppCompatActivity() {
apiService = ApiConfig.getApiService(sessionManager)
locationManager = getSystemService(LOCATION_SERVICE) as LocationManager
WindowCompat.setDecorFitsSystemWindows(window, false)
enableEdgeToEdge()
// Apply insets to your root layout
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
val systemBars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
view.setPadding(
systemBars.left,
systemBars.top,
systemBars.right,
systemBars.bottom
)
windowInsets
}
// Get user profile from session manager
// profileUser =UserProfile.
viewModel.userProfile.observe(this){ user ->

View File

@ -2,8 +2,12 @@ package com.alya.ecommerce_serang.ui.order.address
import android.content.Intent
import android.os.Bundle
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.core.view.isVisible
import androidx.recyclerview.widget.LinearLayoutManager
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
@ -32,6 +36,22 @@ class AddressActivity : AppCompatActivity() {
sessionManager = SessionManager(this)
WindowCompat.setDecorFitsSystemWindows(window, false)
enableEdgeToEdge()
// Apply insets to your root layout
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()
setupRecyclerView()
@ -40,19 +60,17 @@ class AddressActivity : AppCompatActivity() {
viewModel.fetchAddresses()
}
private fun addAddressClicked(){
binding.addAddressClick.setOnClickListener{
val intent = Intent(this, AddAddressActivity::class.java)
startActivity(intent)
}
}
private fun setupToolbar() {
// Remove duplicate toolbar setup
addAddressClicked()
binding.toolbar.setNavigationOnClickListener {
onBackPressedWithResult()
}
binding.addAddressClick.setOnClickListener{
val intent = Intent(this, AddAddressActivity::class.java)
startActivity(intent)
}
}
private fun setupRecyclerView() {

View File

@ -13,11 +13,15 @@ import android.webkit.MimeTypeMap
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import com.alya.ecommerce_serang.data.api.dto.AddEvidenceMultipartRequest
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
import com.alya.ecommerce_serang.data.repository.OrderRepository
@ -81,14 +85,32 @@ class AddEvidencePaymentActivity : AppCompatActivity() {
}
WindowCompat.setDecorFitsSystemWindows(window, false)
enableEdgeToEdge()
// Apply insets to your root layout
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
val systemBars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
view.setPadding(
systemBars.left,
systemBars.top,
systemBars.right,
systemBars.bottom
)
windowInsets
}
binding.toolbar.navigationIcon.apply {
onBackPressed()
}
setupUI()
viewModel.getOrderDetails(orderId)
setupListeners()
setupObservers()
}
private fun setupUI() {

View File

@ -4,9 +4,13 @@ import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
import com.alya.ecommerce_serang.data.repository.OrderRepository
import com.alya.ecommerce_serang.databinding.ActivityPaymentBinding
@ -39,6 +43,22 @@ class PaymentActivity : AppCompatActivity() {
sessionManager = SessionManager(this)
WindowCompat.setDecorFitsSystemWindows(window, false)
enableEdgeToEdge()
// Apply insets to your root layout
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
val systemBars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
view.setPadding(
systemBars.left,
systemBars.top,
systemBars.right,
systemBars.bottom
)
windowInsets
}
// Mengambil data dari intent
val orderId = intent.getIntExtra("ORDER_ID", 0)
val paymentInfoId = intent.getIntExtra("ORDER_PAYMENT_ID", 0)
@ -50,6 +70,7 @@ class PaymentActivity : AppCompatActivity() {
// Setup toolbar
binding.toolbar.setNavigationOnClickListener {
onBackPressedDispatcher
finish()
}
@ -75,15 +96,6 @@ class PaymentActivity : AppCompatActivity() {
startActivity(intent)
}
// Setup button negosiasi harga
binding.btnNegotiatePrice.setOnClickListener {
// Intent ke activity negosiasi harga
// val intent = Intent(this, NegotiatePriceActivity::class.java)
// intent.putExtra("ORDER_ID", orderId)
// startActivity(intent)
}
// Observe data
observeData()

View File

@ -1,8 +1,12 @@
package com.alya.ecommerce_serang.ui.order.history
import android.os.Bundle
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.fragment.app.commit
import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
@ -31,6 +35,22 @@ class HistoryActivity : AppCompatActivity() {
sessionManager = SessionManager(this)
WindowCompat.setDecorFitsSystemWindows(window, false)
enableEdgeToEdge()
// Apply insets to your root layout
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()
if (savedInstanceState == null) {
@ -44,6 +64,7 @@ class HistoryActivity : AppCompatActivity() {
binding.btnBack.setOnClickListener {
onBackPressed()
finish()
}
}

View File

@ -106,12 +106,21 @@ class DetailOrderStatusActivity : AppCompatActivity() {
return
}
setupToolbar()
setupObservers()
loadOrderDetails()
Log.d(TAG, "onCreate: Activity initialization completed")
}
private fun setupToolbar(){
binding.header.headerLeftIcon.setOnClickListener{
finish()
}
binding.header.headerTitle.text = "Detail Pesanan"
}
private fun setupObservers() {
Log.d(TAG, "setupObservers: Setting up LiveData observers")

View File

@ -33,6 +33,7 @@ import com.alya.ecommerce_serang.ui.cart.CartActivity
import com.alya.ecommerce_serang.ui.chat.ChatActivity
import com.alya.ecommerce_serang.ui.home.HorizontalProductAdapter
import com.alya.ecommerce_serang.ui.order.CheckoutActivity
import com.alya.ecommerce_serang.ui.product.storeDetail.StoreDetailActivity
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
import com.alya.ecommerce_serang.utils.SessionManager
import com.bumptech.glide.Glide
@ -185,12 +186,13 @@ class DetailProductActivity : AppCompatActivity() {
binding.recyclerViewOtherProducts.visibility = View.VISIBLE
binding.tvViewAllProducts.visibility = View.VISIBLE
productAdapter?.updateProducts(products)
} }
}
}
private fun setupUI() {
// binding.btnBack.setOnClickListener {
// finish()
// }
binding.searchContainer.btnBack.setOnClickListener {
finish()
}
binding.tvViewAllReviews.setOnClickListener {
viewModel.productDetail.value?.productId?.let { productId ->
@ -198,8 +200,6 @@ class DetailProductActivity : AppCompatActivity() {
}
}
val searchContainerView = binding.searchContainer
searchContainerView.btnCart.setOnClickListener{
navigateToCart()
@ -244,6 +244,10 @@ class DetailProductActivity : AppCompatActivity() {
}
}
binding.containerStoreDetail.setOnClickListener{
handleStoreClick(product)
}
binding.btnAddToCart.setOnClickListener {
viewModel.productDetail.value?.productId?.let { id ->
showAddToCartPopup(id)
@ -317,6 +321,12 @@ class DetailProductActivity : AppCompatActivity() {
startActivity(intent)
}
private fun handleStoreClick(product: Product) {
val intent = Intent(this, StoreDetailActivity::class.java)
intent.putExtra("STORE_ID", product.storeId) // Pass product ID
startActivity(intent)
}
private fun showBuyNowPopup(productId: Int) {
showQuantityDialog(productId, true)
}

View File

@ -0,0 +1,178 @@
package com.alya.ecommerce_serang.ui.product.storeDetail
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
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.LinearLayoutManager
import com.alya.ecommerce_serang.BuildConfig.BASE_URL
import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.data.api.dto.ProductsItem
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreProduct
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
import com.alya.ecommerce_serang.data.repository.ProductRepository
import com.alya.ecommerce_serang.data.repository.Result
import com.alya.ecommerce_serang.databinding.ActivityStoreDetailBinding
import com.alya.ecommerce_serang.ui.cart.CartActivity
import com.alya.ecommerce_serang.ui.home.HorizontalProductAdapter
import com.alya.ecommerce_serang.ui.product.DetailProductActivity
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
import com.alya.ecommerce_serang.utils.SessionManager
import com.bumptech.glide.Glide
class StoreDetailActivity : AppCompatActivity() {
private lateinit var binding: ActivityStoreDetailBinding
private lateinit var apiService: ApiService
private lateinit var sessionManager: SessionManager
private var productAdapter: HorizontalProductAdapter? = null
private val viewModel: StoreDetailViewModel by viewModels {
BaseViewModelFactory {
val apiService = ApiConfig.getApiService(sessionManager)
val productRepository = ProductRepository(apiService)
StoreDetailViewModel(productRepository)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityStoreDetailBinding.inflate(layoutInflater)
setContentView(binding.root)
sessionManager = SessionManager(this)
apiService = ApiConfig.getApiService(sessionManager)
WindowCompat.setDecorFitsSystemWindows(window, false)
enableEdgeToEdge()
// Apply insets to your root layout
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
val systemBars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
view.setPadding(
systemBars.left,
systemBars.top,
systemBars.right,
systemBars.bottom
)
windowInsets
}
setupUI()
setupObservers()
loadData()
}
private fun setupUI() {
binding.searchContainer.btnBack.setOnClickListener {
finish()
}
val searchContainerView = binding.searchContainer
searchContainerView.btnCart.setOnClickListener{
navigateToCart()
}
setupRecyclerViewOtherProducts()
}
private fun setupObservers(){
viewModel.storeDetail.observe(this) { result ->
when (result) {
is Result.Success -> {
updateStoreInfo(result.data)
viewModel.loadOtherProducts(result.data.storeId)
}
is Result.Error -> {
// Show error message, maybe a Toast or Snackbar
Toast.makeText(this, "Failed to load store: ${result.exception.message}", Toast.LENGTH_SHORT).show()
}
is Result.Loading -> {
// Show loading indicator if needed
}
}
}
viewModel.otherProducts.observe(this) { products ->
updateOtherProducts(products)
}
}
private fun loadData() {
val storeId = intent.getIntExtra("STORE_ID", -1)
if (storeId == -1) {
Log.e("StoreDetailActivity", "Invalid store ID")
Toast.makeText(this, "Invalid store ID", Toast.LENGTH_SHORT).show()
finish() // Close activity if no valid ID
return
}
viewModel.loadStoreDetail(storeId)
}
private fun updateStoreInfo(store: StoreProduct?) {
store?.let {
binding.tvStoreName.text = it.storeName
binding.tvStoreRating.text = it.storeRating
binding.tvStoreLocation.text = it.storeLocation
binding.tvStoreType.text = it.storeType
binding.tvActiveStatus.text = it.status
// Load store image using Glide
val fullImageUrl = when (val img = it.storeImage) {
is String -> {
if (img.startsWith("/")) BASE_URL + img.substring(1) else img
}
else -> R.drawable.placeholder_image
}
Glide.with(this)
.load(fullImageUrl)
.placeholder(R.drawable.placeholder_image)
.into(binding.ivStoreImage)
}
}
private fun updateOtherProducts(products: List<ProductsItem>) {
if (products.isEmpty()) {
binding.rvProducts.visibility = View.GONE
} else {
binding.rvProducts.visibility = View.VISIBLE
productAdapter?.updateProducts(products)
}
}
private fun setupRecyclerViewOtherProducts(){
productAdapter = HorizontalProductAdapter(
products = emptyList(),
onClick = { productsItem -> handleProductClick(productsItem) }
)
binding.rvProducts.apply {
adapter = productAdapter
layoutManager = LinearLayoutManager(
context,
LinearLayoutManager.HORIZONTAL,
false
)
}
}
private fun handleProductClick(product: ProductsItem) {
val intent = Intent(this, DetailProductActivity::class.java)
intent.putExtra("PRODUCT_ID", product.id) // Pass product ID
startActivity(intent)
}
private fun navigateToCart() {
val intent = Intent(this, CartActivity::class.java)
startActivity(intent)
}
}

View File

@ -0,0 +1,87 @@
package com.alya.ecommerce_serang.ui.product.storeDetail
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.ProductsItem
import com.alya.ecommerce_serang.data.api.response.customer.product.Product
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreProduct
import com.alya.ecommerce_serang.data.repository.ProductRepository
import com.alya.ecommerce_serang.data.repository.Result
import kotlinx.coroutines.launch
class StoreDetailViewModel (private val repository: ProductRepository
): ViewModel() {
private val _productDetail = MutableLiveData<Product?>()
val productDetail: LiveData<Product?> get() = _productDetail
private val _otherProducts = MutableLiveData<List<ProductsItem>>()
val otherProducts: LiveData<List<ProductsItem>> get() = _otherProducts
private val _isLoading = MutableLiveData<Boolean>()
val isLoading: LiveData<Boolean> get() = _isLoading
private val _error = MutableLiveData<String>()
val error: LiveData<String> get() = _error
private val _storeDetail = MutableLiveData<Result<StoreProduct>>()
val storeDetail : LiveData<Result<StoreProduct>> get() = _storeDetail
fun loadOtherProducts(storeId: Int) {
viewModelScope.launch {
try {
val result = repository.getAllProducts() // Fetch products
if (result is Result.Success) {
val allProducts = result.data // Extract the list
val filteredProducts = allProducts.filter {
it.storeId == storeId && it.id != _productDetail.value?.productId
} // Filter by storeId and exclude current product
_otherProducts.value = filteredProducts // Update LiveData
} else if (result is Result.Error) {
Log.e("ProductViewModel", "Error loading other products: ${result.exception.message}")
_otherProducts.value = emptyList() // Set empty list on failure
}
} catch (e: Exception) {
Log.e("ProductViewModel", "Exception loading other products: ${e.message}")
_otherProducts.value = emptyList()
}
}
}
fun loadProductDetail(productId: Int) {
_isLoading.value = true
viewModelScope.launch {
try {
val result = repository.fetchProductDetail(productId)
_productDetail.value = result?.product
//Load store details if product has a store ID
result?.product?.storeId?.let { storeId ->
loadStoreDetail(storeId)
}
} catch (e: Exception) {
Log.e("ProductViewModel", "Error loading product details: ${e.message}")
_error.value = "Failed to load product details: ${e.message}"
} finally {
_isLoading.value = false
}
}
}
fun loadStoreDetail(storeId: Int) {
viewModelScope.launch {
try {
_storeDetail.value = Result.Loading
val result = repository.fetchStoreDetail(storeId)
_storeDetail.value = result
} catch (e: Exception) {
Log.e("ProductViewModel", "Error loading store details: ${e.message}")
_storeDetail.value = Result.Error(e)
}
}
}
}

View File

@ -63,16 +63,19 @@ class ProfileFragment : Fragment() {
viewModel.loadUserProfile()
viewModel.checkStoreUser()
binding.cardBukaToko.setOnClickListener{
val hasStore = viewModel.checkStore.value
// val hasStore = false
Log.d("Profile Fragment", "Check store $hasStore")
if (hasStore == true){
binding.tvBukaToko.text = "Buka Toko Saya"
val intentBuka = Intent(requireContext(), MyStoreActivity::class.java)
startActivity(intentBuka)
} else {
binding.tvBukaToko.text = "Daftar Toko Saya"
val intentBuka = Intent(requireContext(), RegisterStoreActivity::class.java)
startActivity(intentBuka)
}

View File

@ -1,11 +1,11 @@
package com.alya.ecommerce_serang.ui.profile.mystore.sells
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager
import com.alya.ecommerce_serang.data.api.response.store.orders.OrdersItem
@ -104,7 +104,7 @@ class SellsListFragment : Fragment() {
} else {
binding.tvEmptyState.visibility = View.GONE
binding.rvSells.visibility = View.VISIBLE
//sellsAdapter.submitList(result.data)
sellsAdapter.submitList(result.data)
}
}
is ViewState.Error -> {

View File

@ -28,7 +28,7 @@ class ProfileViewModel(private val userRepository: UserRepository) : ViewModel()
val checkStore: LiveData<Boolean> = _checkStore
private val _logout = MutableLiveData<Boolean>()
val logout : LiveData<Boolean> = _checkStore
val logout : LiveData<Boolean> = _logout
fun loadUserProfile(){
viewModelScope.launch {

View File

@ -17,8 +17,8 @@ class SellsViewModel(private val repository: SellsRepository) : ViewModel() {
private const val TAG = "SellsViewModel"
}
private val _sells = MutableLiveData<ViewState<List<OrdersItem?>?>>()
val sells: LiveData<ViewState<List<OrdersItem?>?>> = _sells
private val _sells = MutableLiveData<ViewState<List<OrdersItem>>>()
val sells: LiveData<ViewState<List<OrdersItem>>> = _sells
fun getSellList(status: String) {
_sells.value = ViewState.Loading

View File

@ -225,16 +225,6 @@
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tvStoreName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="SnackEnak"
android:fontFamily="@font/dmsans_semibold"
android:textColor="@color/black"
android:textSize="16sp"
android:textStyle="bold" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvOrderItems"
android:layout_width="match_parent"
@ -310,10 +300,11 @@
android:orientation="horizontal">
<TextView
android:id="@+id/tv_item_count"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="1 item"
android:text="Harga Total Produk"
android:textColor="@color/black_400"
android:textSize="14sp" />

View File

@ -22,7 +22,7 @@
<include
android:id="@+id/searchContainer"
layout="@layout/view_search"
layout="@layout/view_search_back"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
@ -196,9 +196,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<!-- Buyer Reviews Section -->
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
@ -377,6 +374,7 @@
<!-- Seller Info Section -->
<androidx.cardview.widget.CardView
android:id="@+id/container_store_detail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="0dp">

View File

@ -6,7 +6,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
android:layout_margin="16dp"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="16dp"
tools:context=".ui.auth.LoginActivity">
@ -94,6 +94,7 @@
android:text="@string/no_account"/>
<TextView
android:id="@+id/tv_registrasi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/signup"

View File

@ -221,15 +221,6 @@
android:padding="16dp"
app:layout_constraintBottom_toBottomOf="parent">
<com.google.android.material.button.MaterialButton
android:id="@+id/btnNegotiatePrice"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:background="@drawable/bg_button_outline"
android:text="Negosiasi Harga"
android:textAllCaps="false"
android:textColor="@color/blue_500" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnUploadPaymentProof"

View File

@ -9,6 +9,17 @@
android:theme="@style/Theme.Ecommerce_serang"
tools:context=".ui.auth.RegisterActivity">
<TextView
android:id="@+id/tv_title_register"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="16dp"
android:text="Daftar Akun"
android:textAlignment="center"
android:textSize="20sp"
android:textStyle="bold" />
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/registration_progress"
android:layout_width="match_parent"

View File

@ -0,0 +1,171 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.product.storeDetail.StoreDetailActivity">
<include
android:id="@+id/searchContainer"
layout="@layout/view_search_back"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:layout_constraintTop_toTopOf="parent" />
<!-- Store Information -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/storeInfoContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/blue_50"
android:layout_marginTop="16dp"
android:padding="24dp"
app:layout_constraintTop_toBottomOf="@id/searchContainer">
<ImageView
android:id="@+id/ivStoreImage"
android:layout_width="64dp"
android:layout_height="64dp"
android:background="@drawable/circle_background"
android:scaleType="centerCrop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/placeholder_image" />
<TextView
android:id="@+id/tvStoreName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:textColor="@android:color/black"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/ivStoreImage"
app:layout_constraintTop_toTopOf="@id/ivStoreImage"
tools:text="SnackEnak" />
<TextView
android:id="@+id/tvStoreType"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/ivStoreImage"
app:layout_constraintTop_toBottomOf="@id/tvStoreName"
tools:text="Makanan Ringan" />
<LinearLayout
android:id="@+id/storeRatingContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:gravity="center_vertical"
android:orientation="horizontal"
app:layout_constraintStart_toEndOf="@id/ivStoreImage"
app:layout_constraintTop_toBottomOf="@id/tvStoreType">
<ImageView
android:id="@+id/ivStoreRatingStar"
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/ic_star"
app:tint="@color/yellow" />
<TextView
android:id="@+id/tvStoreRating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:textSize="12sp"
android:textStyle="bold"
tools:text="5.0" />
</LinearLayout>
<TextView
android:id="@+id/tvStoreLocation"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="16dp"
android:textSize="12sp"
app:layout_constraintEnd_toStartOf="@id/tvActiveStatus"
app:layout_constraintStart_toEndOf="@id/ivStoreImage"
app:layout_constraintTop_toBottomOf="@id/storeRatingContainer"
tools:text="Kabupaten Serang" />
<TextView
android:id="@+id/tvActiveStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="4dp"
android:paddingEnd="4dp"
android:text="Aktif"
android:textColor="@android:color/black"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@id/tvStoreLocation"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tvStoreLocation" />
<!-- <ImageButton-->
<!-- android:id="@+id/btnChevron"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:background="?attr/selectableItemBackgroundBorderless"-->
<!-- android:contentDescription="More"-->
<!-- android:src="@drawable/ic_chevron_right"-->
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent" />-->
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.divider.MaterialDivider
android:id="@+id/divider_product"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/storeInfoContainer"/>
<!-- Tab Layout: TO DO implement after review -->
<!-- <com.google.android.material.tabs.TabLayout-->
<!-- android:id="@+id/tabLayout"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- app:layout_constraintTop_toBottomOf="@id/storeInfoContainer"-->
<!-- app:tabIndicatorColor="@color/colorPrimary"-->
<!-- app:tabSelectedTextColor="@color/colorPrimary"-->
<!-- app:tabTextColor="@android:color/darker_gray">-->
<!-- <com.google.android.material.tabs.TabItem-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="Produk" />-->
<!-- <com.google.android.material.tabs.TabItem-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="Kategori" />-->
<!-- </com.google.android.material.tabs.TabLayout>-->
<!-- Products RecyclerView -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_products"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintTop_toBottomOf="@id/divider_product"
tools:itemCount="5"
tools:listitem="@layout/item_section_horizontal" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -53,51 +53,59 @@
app:layout_constraintTop_toTopOf="@id/profileImage" />
<!-- Store Button -->
<androidx.cardview.widget.CardView
android:id="@+id/cardBukaToko"
<LinearLayout
android:id="@+id/container_buka_toko"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:layout_marginTop="16dp"
android:clickable="true"
android:focusable="true"
app:cardElevation="4dp"
android:orientation="vertical"
app:layout_constraintTop_toBottomOf="@id/profileImage">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_marginHorizontal="14dp"
android:layout_gravity="center"
<androidx.cardview.widget.CardView
android:id="@+id/cardBukaToko"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:clickable="true"
android:focusable="true"
android:paddingHorizontal="16dp"
app:cardElevation="4dp"
tools:layout_editor_absoluteX="0dp">
<TextView
android:id="@+id/tvBukaToko"
android:layout_width="0dp"
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/outline_store_24"
android:drawablePadding="16dp"
android:padding="16dp"
android:fontFamily="@font/dmsans_semibold"
android:textSize="14sp"
android:text="@string/open_store"
app:layout_constraintEnd_toStartOf="@id/ivStoreArrow"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
android:layout_gravity="center"
android:layout_marginHorizontal="14dp">
<ImageButton
android:id="@+id/ivStoreArrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_arrow_right"
app:layout_constraintBottom_toBottomOf="@id/tvBukaToko"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tvBukaToko" />
<TextView
android:id="@+id/tvBukaToko"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableStart="@drawable/outline_store_24"
android:drawablePadding="16dp"
android:fontFamily="@font/dmsans_semibold"
android:padding="16dp"
android:text="@string/open_store"
android:textSize="14sp"
app:layout_constraintEnd_toStartOf="@id/ivStoreArrow"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<ImageView
android:id="@+id/ivStoreArrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_arrow_right"
app:layout_constraintBottom_toBottomOf="@id/tvBukaToko"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tvBukaToko" />
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
<androidx.cardview.widget.CardView
android:id="@+id/cardPesanan"
@ -105,7 +113,7 @@
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@id/cardBukaToko">
app:layout_constraintTop_toBottomOf="@id/container_buka_toko">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"

View File

@ -6,6 +6,19 @@
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="@+id/tvStoreName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="SnackEnak"
android:fontFamily="@font/dmsans_semibold"
android:textColor="@color/black"
android:paddingBottom="8dp"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<ImageView
android:id="@+id/ivProduct"
android:layout_width="64dp"
@ -13,7 +26,7 @@
android:scaleType="centerCrop"
android:elevation="4dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvStoreName"
tools:src="@drawable/placeholder_image" />
<TextView

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ImageButton
android:id="@+id/btn_back"
android:layout_width="48dp"
android:layout_height="0dp"
android:layout_marginEnd="0dp"
android:padding="8dp"
android:backgroundTint="@color/white"
android:src="@drawable/baseline_arrow_back_24"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toStartOf="@id/search"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<EditText
android:id="@+id/search"
android:layout_width="0dp"
android:layout_height="48dp"
android:background="@drawable/search_background"
android:hint="@string/fragment_home_search"
android:textColor="@color/soft_gray"
android:textSize="16sp"
android:fontFamily="@font/dmsans_regular"
android:layout_marginStart="8dp"
android:drawablePadding="8dp"
android:paddingHorizontal="25dp"
android:imeOptions="actionSearch"
android:inputType="text"
app:layout_constraintEnd_toStartOf="@id/btn_cart"
app:layout_constraintTop_toTopOf="parent"
android:drawableStart="@drawable/baseline_search_24"
app:layout_constraintStart_toEndOf="@id/btn_back"/>
<ImageButton
android:id="@+id/btn_cart"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="8dp"
android:padding="8dp"
android:backgroundTint="@color/white"
android:src="@drawable/outline_shopping_cart_24"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintBottom_toBottomOf="@id/search"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/search"/>
</androidx.constraintlayout.widget.ConstraintLayout>