Compare commits

...

8 Commits

Author SHA1 Message Date
29fb55e3c0 fix restore 2025-08-22 14:54:28 +07:00
2f16542e5e fix UI evidence 2025-08-22 14:38:02 +07:00
2f28a23114 Merge remote-tracking branch 'origin/master' 2025-08-22 13:47:20 +07:00
94c081e839 fix UI 2025-08-22 13:46:42 +07:00
d32bdf65fe update checkout 2025-08-22 13:08:06 +07:00
9162b2cc60 update detail store 2025-08-22 12:11:54 +07:00
8eac90311e fix search bar 2025-08-22 11:31:52 +07:00
9cd0675d82 fix progress bar loading 2025-08-22 11:21:07 +07:00
33 changed files with 1067 additions and 528 deletions

View File

@ -86,19 +86,72 @@ class RegisterActivity : AppCompatActivity() {
} }
} }
// In RegisterActivity, add debug to navigateToStep:
fun navigateToStep(step: Int, userData: RegisterRequest?) { fun navigateToStep(step: Int, userData: RegisterRequest?) {
val fragment = when (step) { Log.d("RegisterActivity", "=== NAVIGATE TO STEP START ===")
1 -> RegisterStep1Fragment.newInstance() Log.d("RegisterActivity", "Target step: $step")
2 -> RegisterStep2Fragment.newInstance(userData) Log.d("RegisterActivity", "Current fragment count: ${supportFragmentManager.fragments.size}")
3 -> RegisterStep3Fragment.newInstance() Log.d("RegisterActivity", "UserData: ${userData?.email}")
else -> null
Log.d("RegisterActivity", "Navigation called from:")
Thread.currentThread().stackTrace.take(10).forEach { element ->
Log.d("RegisterActivity", " at ${element.className}.${element.methodName}(${element.fileName}:${element.lineNumber})")
} }
fragment?.let {
supportFragmentManager.beginTransaction() try {
.replace(R.id.fragment_container, it) val fragment = when (step) {
.addToBackStack(null) 1 -> {
.commit() Log.d("RegisterActivity", "Creating RegisterStep1Fragment")
RegisterStep1Fragment.newInstance()
}
2 -> {
Log.d("RegisterActivity", "Creating RegisterStep2Fragment")
RegisterStep2Fragment.newInstance(userData)
}
3 -> {
Log.d("RegisterActivity", "Creating RegisterStep3Fragment")
RegisterStep3Fragment.newInstance()
}
else -> {
Log.e("RegisterActivity", "Invalid step: $step")
return
}
}
Log.d("RegisterActivity", "Fragment created, starting transaction")
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.fragment_container, fragment)
Log.d("RegisterActivity", "About to commit transaction")
transaction.commit()
Log.d("RegisterActivity", "Transaction committed")
// Update ViewModel step
registerViewModel.setStep(step)
Log.d("RegisterActivity", "ViewModel step updated to: $step")
} catch (e: Exception) {
Log.e("RegisterActivity", "Exception in navigateToStep: ${e.message}", e)
e.printStackTrace()
}
Log.d("RegisterActivity", "=== NAVIGATE TO STEP END ===")
}
// Handle Android back button - close activity or go to step 1
override fun onBackPressed() {
val currentStep = registerViewModel.currentStep.value ?: 1
if (currentStep == 1) {
// On step 1, exit the activity
super.onBackPressed()
} else {
// On other steps, go back to step 1
navigateToStep(1, null)
} }
} }
} }

View File

@ -1,6 +1,7 @@
package com.alya.ecommerce_serang.ui.auth.fragments package com.alya.ecommerce_serang.ui.auth.fragments
import android.content.Context import android.content.Context
import android.content.Intent
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.CountDownTimer import android.os.CountDownTimer
@ -32,6 +33,9 @@ class RegisterStep2Fragment : Fragment() {
private var _binding: FragmentRegisterStep2Binding? = null private var _binding: FragmentRegisterStep2Binding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
private lateinit var sessionManager: SessionManager private lateinit var sessionManager: SessionManager
private var countDownTimer: CountDownTimer? = null
private var timeRemaining = 30
private var isTimerRunning = false
// In RegisterStep2Fragment AND RegisterStep3Fragment: // In RegisterStep2Fragment AND RegisterStep3Fragment:
private val registerViewModel: RegisterViewModel by activityViewModels { private val registerViewModel: RegisterViewModel by activityViewModels {
@ -42,8 +46,8 @@ class RegisterStep2Fragment : Fragment() {
RegisterViewModel(userRepository, orderRepository, requireContext()) RegisterViewModel(userRepository, orderRepository, requireContext())
} }
} }
private var countDownTimer: CountDownTimer? = null // private var countDownTimer: CountDownTimer? = null
private var timeRemaining = 30 // 30 seconds cooldown for resend // private var timeRemaining = 30 // 30 seconds cooldown for resend
companion object { companion object {
@ -112,13 +116,23 @@ class RegisterStep2Fragment : Fragment() {
} }
} }
binding.btnBack.setOnClickListener {
parentFragmentManager.popBackStack()
}
observeRegistrationState() observeRegistrationState()
observeLoginState() observeLoginState()
Log.d(TAG, "Registration and login state observers set up") Log.d(TAG, "Registration and login state observers set up")
binding.btnBack.setOnClickListener {
Log.d(TAG, "Back button clicked - cleaning up timer and going to step 1")
// Stop the timer before navigating
stopTimer()
// Small delay to ensure timer is properly canceled
binding.root.postDelayed({
// (activity as? RegisterActivity)?.navigateToStep(1, null)
val intent = Intent(requireContext(), RegisterActivity::class.java)
startActivity(intent)
requireActivity().finish()
}, 100)
}
} }
private fun verifyOtp(userData: RegisterRequest?) { private fun verifyOtp(userData: RegisterRequest?) {
@ -172,37 +186,9 @@ class RegisterStep2Fragment : Fragment() {
} ?: Log.e(TAG, "Cannot resend OTP: email is null") } ?: Log.e(TAG, "Cannot resend OTP: email is null")
} }
private fun startResendCooldown() {
Log.d(TAG, "startResendCooldown called")
timeRemaining = 30
binding.tvResendOtp.isEnabled = false
binding.tvResendOtp.setTextColor(ContextCompat.getColor(requireContext(), R.color.soft_gray))
countDownTimer?.cancel()
countDownTimer = object : CountDownTimer(30000, 1000) {
override fun onTick(millisUntilFinished: Long) {
timeRemaining = (millisUntilFinished / 1000).toInt()
binding.tvTimer.text = "Kirim ulang OTP dalam waktu 00:${String.format("%02d", timeRemaining)}"
if (timeRemaining % 5 == 0) {
Log.d(TAG, "Cooldown remaining: $timeRemaining seconds")
}
}
override fun onFinish() {
Log.d(TAG, "Cooldown finished, enabling resend button")
binding.tvTimer.text = "Dapat mengirim ulang kode OTP"
binding.tvResendOtp.isEnabled = true
binding.tvResendOtp.setTextColor(ContextCompat.getColor(requireContext(), R.color.blue1))
timeRemaining = 0
}
}.start()
}
private fun observeRegistrationState() { private fun observeRegistrationState() {
registerViewModel.message.observe(viewLifecycleOwner) { message -> registerViewModel.message.observe(viewLifecycleOwner) { message ->
Log.d(TAG, "Message from server: $message") Log.d(TAG, "Message from server: $message")
// You can use the message here if needed, e.g., for showing in a specific UI element
// or for storing for later use
} }
registerViewModel.registerState.observe(viewLifecycleOwner) { result -> registerViewModel.registerState.observe(viewLifecycleOwner) { result ->
when (result) { when (result) {
@ -314,9 +300,117 @@ class RegisterStep2Fragment : Fragment() {
} }
override fun onDestroyView() { private fun startResendCooldown() {
super.onDestroyView() Log.d(TAG, "startResendCooldown called")
// Cancel any existing timer first
stopTimer()
timeRemaining = 30
isTimerRunning = true
binding.tvResendOtp.isEnabled = false
binding.tvResendOtp.setTextColor(ContextCompat.getColor(requireContext(), R.color.soft_gray))
countDownTimer = object : CountDownTimer(30000, 1000) {
override fun onTick(millisUntilFinished: Long) {
if (!isTimerRunning) {
cancel()
return
}
timeRemaining = (millisUntilFinished / 1000).toInt()
// Check if fragment is still attached before updating UI
if (isAdded && _binding != null) {
binding.tvTimer.text = "Kirim ulang OTP dalam waktu 00:${String.format("%02d", timeRemaining)}"
if (timeRemaining % 5 == 0) {
Log.d(TAG, "Cooldown remaining: $timeRemaining seconds")
}
}
}
override fun onFinish() {
if (!isTimerRunning) return
Log.d(TAG, "Cooldown finished, enabling resend button")
// Check if fragment is still attached before updating UI
if (isAdded && _binding != null) {
binding.tvTimer.text = "Dapat mengirim ulang kode OTP"
binding.tvResendOtp.isEnabled = true
binding.tvResendOtp.setTextColor(ContextCompat.getColor(requireContext(), R.color.blue1))
timeRemaining = 0
}
isTimerRunning = false
}
}.start()
}
private fun stopTimer() {
Log.d(TAG, "stopTimer called")
isTimerRunning = false
countDownTimer?.cancel() countDownTimer?.cancel()
countDownTimer = null
}
override fun onPause() {
super.onPause()
Log.d(TAG, "onPause - stopping timer")
stopTimer()
}
override fun onStop() {
super.onStop()
Log.d(TAG, "onStop - stopping timer")
stopTimer()
}
override fun onDestroyView() {
Log.d(TAG, "onDestroyView - cleaning up")
super.onDestroyView()
// Ensure timer is stopped
stopTimer()
_binding = null _binding = null
} }
override fun onDetach() {
super.onDetach()
Log.d(TAG, "onDetach - final cleanup")
stopTimer()
}
} }
// override fun onDestroyView() {
// super.onDestroyView()
// countDownTimer?.cancel()
// _binding = null
// }
// private fun startResendCooldown() {
// Log.d(TAG, "startResendCooldown called")
// timeRemaining = 30
// binding.tvResendOtp.isEnabled = false
// binding.tvResendOtp.setTextColor(ContextCompat.getColor(requireContext(), R.color.soft_gray))
//
// countDownTimer?.cancel()
// countDownTimer = object : CountDownTimer(30000, 1000) {
// override fun onTick(millisUntilFinished: Long) {
// timeRemaining = (millisUntilFinished / 1000).toInt()
// binding.tvTimer.text = "Kirim ulang OTP dalam waktu 00:${String.format("%02d", timeRemaining)}"
// if (timeRemaining % 5 == 0) {
// Log.d(TAG, "Cooldown remaining: $timeRemaining seconds")
// }
// }
//
// override fun onFinish() {
// Log.d(TAG, "Cooldown finished, enabling resend button")
// binding.tvTimer.text = "Dapat mengirim ulang kode OTP"
// binding.tvResendOtp.isEnabled = true
// binding.tvResendOtp.setTextColor(ContextCompat.getColor(requireContext(), R.color.blue1))
// timeRemaining = 0
// }
// }.start()
// }

View File

@ -6,6 +6,7 @@ import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
@ -32,6 +33,7 @@ import com.alya.ecommerce_serang.utils.SessionManager
import com.alya.ecommerce_serang.utils.setLightStatusBar import com.alya.ecommerce_serang.utils.setLightStatusBar
import com.alya.ecommerce_serang.utils.viewmodel.HomeUiState import com.alya.ecommerce_serang.utils.viewmodel.HomeUiState
import com.alya.ecommerce_serang.utils.viewmodel.HomeViewModel import com.alya.ecommerce_serang.utils.viewmodel.HomeViewModel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
//@AndroidEntryPoint //@AndroidEntryPoint
@ -140,12 +142,13 @@ class HomeFragment : Fragment() {
viewModel.uiState.collect { state -> viewModel.uiState.collect { state ->
when (state) { when (state) {
is HomeUiState.Loading -> { is HomeUiState.Loading -> {
binding.loading.root.isVisible = true binding.loadingAll.root.visibility = View.VISIBLE
binding.error.root.isVisible = false binding.error.root.isVisible = false
binding.home.isVisible = false binding.home.isVisible = false
delay(5000)
} }
is HomeUiState.Success -> { is HomeUiState.Success -> {
binding.loading.root.isVisible = false binding.loadingAll.root.visibility = View.GONE
binding.error.root.isVisible = false binding.error.root.isVisible = false
binding.home.isVisible = true binding.home.isVisible = true
val products = state.products val products = state.products
@ -154,10 +157,12 @@ class HomeFragment : Fragment() {
productAdapter?.updateLimitedProducts(products) productAdapter?.updateLimitedProducts(products)
} }
is HomeUiState.Error -> { is HomeUiState.Error -> {
binding.loading.root.isVisible = false binding.loadingAll.root.visibility = View.GONE
binding.error.root.isVisible = true binding.error.root.isVisible = true
binding.home.isVisible = false binding.home.isVisible = false
binding.error.errorMessage.text = state.message // binding.error.errorMessage.text = state.message
Log.e("HomeFragment", "Error load data: ${state.message}")
Toast.makeText(requireContext(), "Terjadi kendala. Muat ulang halaman", Toast.LENGTH_SHORT) .show()
binding.error.retryButton.setOnClickListener { binding.error.retryButton.setOnClickListener {
viewModel.retry() viewModel.retry()
} }

View File

@ -7,12 +7,15 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.data.api.dto.ProductsItem import com.alya.ecommerce_serang.data.api.dto.ProductsItem
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
import com.alya.ecommerce_serang.data.repository.ProductRepository import com.alya.ecommerce_serang.data.repository.ProductRepository
@ -106,6 +109,11 @@ class SearchHomeFragment : Fragment() {
} }
}) })
val searchText = findViewById<TextView>(androidx.appcompat.R.id.search_src_text)
searchText.textSize = 14f // in sp
searchText.setHintTextColor(ContextCompat.getColor(context, R.color.black_200))
searchText.setTextColor(ContextCompat.getColor(context, R.color.black))
if (args.query.isNullOrEmpty()) { if (args.query.isNullOrEmpty()) {
requestFocus() requestFocus()
post { post {

View File

@ -154,8 +154,18 @@ class CheckoutActivity : AppCompatActivity() {
// Observe address details // Observe address details
viewModel.addressDetails.observe(this) { address -> viewModel.addressDetails.observe(this) { address ->
binding.tvPlacesAddress.text = address?.recipient if (address != null) {
binding.tvAddress.text = "${address?.street}, ${address?.subdistrict}" // Show selected address
binding.containerEmptyAddress.visibility = View.GONE
binding.containerAddress.visibility = View.VISIBLE
binding.tvPlacesAddress.text = address.recipient
binding.tvAddress.text = "${address.street}, ${address.subdistrict}"
} else {
// Show empty address state
binding.containerEmptyAddress.visibility = View.VISIBLE
binding.containerAddress.visibility = View.GONE
}
} }
viewModel.availablePaymentMethods.observe(this) { paymentMethods -> viewModel.availablePaymentMethods.observe(this) { paymentMethods ->
@ -172,9 +182,7 @@ class CheckoutActivity : AppCompatActivity() {
// Update the adapter ONLY if it exists // Update the adapter ONLY if it exists
paymentAdapter?.let { adapter -> paymentAdapter?.let { adapter ->
// This line was causing issues - using setSelectedPayment instead of setSelectedPaymentName
adapter.setSelectedPaymentId(selectedPayment.id) adapter.setSelectedPaymentId(selectedPayment.id)
Log.d("CheckoutActivity", "Updated adapter with selected payment: ${selectedPayment.id}") Log.d("CheckoutActivity", "Updated adapter with selected payment: ${selectedPayment.id}")
} }
} }
@ -183,13 +191,13 @@ class CheckoutActivity : AppCompatActivity() {
// Observe loading state // Observe loading state
viewModel.isLoading.observe(this) { isLoading -> viewModel.isLoading.observe(this) { isLoading ->
binding.btnPay.isEnabled = !isLoading binding.btnPay.isEnabled = !isLoading
} }
// Observe error messages // Observe error messages
viewModel.errorMessage.observe(this) { message -> viewModel.errorMessage.observe(this) { message ->
if (message.isNotEmpty()) { if (message.isNotEmpty()) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show() Toast.makeText(this, "Terdapat kendala di pemesanan", Toast.LENGTH_SHORT).show()
Log.e("CheckoutActivity", "Error from errorMessage: $message")
} }
} }
@ -207,11 +215,16 @@ class CheckoutActivity : AppCompatActivity() {
if (paymentMethods.isEmpty()) { if (paymentMethods.isEmpty()) {
Log.e("CheckoutActivity", "Payment methods list is empty") Log.e("CheckoutActivity", "Payment methods list is empty")
Toast.makeText(this, "Tidak ditemukan metode pembayaran", Toast.LENGTH_SHORT).show() Toast.makeText(this, "Tidak ditemukan metode pembayaran", Toast.LENGTH_SHORT).show()
binding.tvEmptyPayment.visibility = View.VISIBLE
// Show empty payment state
binding.containerEmptyPayment.visibility = View.VISIBLE
binding.rvPaymentInfo.visibility = View.GONE
return return
} }
binding.tvEmptyPayment.visibility = View.GONE binding.containerEmptyPayment.visibility = View.GONE
binding.rvPaymentInfo.visibility = View.VISIBLE
// Debug logging // Debug logging
Log.d("CheckoutActivity", "Setting up payment methods: ${paymentMethods.size} methods available") Log.d("CheckoutActivity", "Setting up payment methods: ${paymentMethods.size} methods available")
@ -268,6 +281,16 @@ class CheckoutActivity : AppCompatActivity() {
this.adapter = adapter this.adapter = adapter
isNestedScrollingEnabled = false isNestedScrollingEnabled = false
} }
// if (checkoutData.cartItems.isEmpty()) {
// // Show empty products state
// binding.containerEmptyProducts.visibility = View.VISIBLE
// binding.rvProductItems.visibility = View.GONE
// return
// }
binding.containerEmptyProducts.visibility = View.GONE
binding.rvProductItems.visibility = View.VISIBLE
} }
private fun updateOrderSummary() { private fun updateOrderSummary() {
@ -292,7 +315,8 @@ class CheckoutActivity : AppCompatActivity() {
private fun updateShippingUI(shipName: String, shipService: String, shipEtd: String, shipPrice: Int) { private fun updateShippingUI(shipName: String, shipService: String, shipEtd: String, shipPrice: Int) {
if (shipName.isNotEmpty() && shipService.isNotEmpty()) { if (shipName.isNotEmpty() && shipService.isNotEmpty()) {
// Display shipping name and service in one line // Hide empty state and show selected shipping
binding.containerEmptyShipping.visibility = View.GONE
binding.cardShipment.visibility = View.VISIBLE binding.cardShipment.visibility = View.VISIBLE
binding.tvCourierName.text = "$shipName $shipService" binding.tvCourierName.text = "$shipName $shipService"
@ -300,6 +324,8 @@ class CheckoutActivity : AppCompatActivity() {
binding.tvShippingPrice.text = formatCurrency(shipPrice.toDouble()) binding.tvShippingPrice.text = formatCurrency(shipPrice.toDouble())
binding.rbJne.isChecked = true binding.rbJne.isChecked = true
} else { } else {
// Show empty shipping state
binding.containerEmptyShipping.visibility = View.VISIBLE
binding.cardShipment.visibility = View.GONE binding.cardShipment.visibility = View.GONE
} }
} }
@ -312,10 +338,10 @@ class CheckoutActivity : AppCompatActivity() {
} }
// Shipping method selection // Shipping method selection
binding.layoutShippingMethod.setOnClickListener { binding.tvShippingOption.setOnClickListener {
val addressId = viewModel.addressDetails.value?.id ?: 0 val addressId = viewModel.addressDetails.value?.id ?: 0
if (addressId <= 0) { if (addressId <= 0) {
Toast.makeText(this, "Silahkan pilih metode pengiriman dahulu", Toast.LENGTH_SHORT).show() Toast.makeText(this, "Silahkan pilih alamat dahulu", Toast.LENGTH_SHORT).show()
return@setOnClickListener return@setOnClickListener
} }

View File

@ -52,12 +52,12 @@ class AddressActivity : AppCompatActivity() {
windowInsets windowInsets
} }
viewModel.fetchAddresses()
setupToolbar() setupToolbar()
setupRecyclerView() setupRecyclerView()
setupObservers() setupObservers()
viewModel.fetchAddresses()
} }
@ -126,6 +126,11 @@ class AddressActivity : AppCompatActivity() {
finish() finish()
} }
override fun onResume() {
super.onResume()
viewModel.fetchAddresses()
}
companion object { companion object {
const val EXTRA_ADDRESS_ID = "extra_address_id" const val EXTRA_ADDRESS_ID = "extra_address_id"
} }

View File

@ -61,8 +61,8 @@ class AddEvidencePaymentActivity : AppCompatActivity() {
} }
private val paymentMethods = arrayOf( private val paymentMethods = arrayOf(
"Pilih Metode Pembayaran",
"Transfer Bank", "Transfer Bank",
"QRIS",
) )
// private val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? -> // private val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
@ -313,10 +313,10 @@ class AddEvidencePaymentActivity : AppCompatActivity() {
return return
} }
if (binding.spinnerPaymentMethod.selectedItemPosition == 0) { // if (binding.spinnerPaymentMethod.selectedItemPosition == 0) {
Toast.makeText(this, "Silahkan pilih metode pembayaran", Toast.LENGTH_SHORT).show() // Toast.makeText(this, "Silahkan pilih metode pembayaran", Toast.LENGTH_SHORT).show()
return // return
} // }
binding.etAccountNumber.visibility = View.GONE binding.etAccountNumber.visibility = View.GONE
// if (binding.etAccountNumber.text.toString().trim().isEmpty()) { // if (binding.etAccountNumber.text.toString().trim().isEmpty()) {
@ -324,10 +324,10 @@ class AddEvidencePaymentActivity : AppCompatActivity() {
// return // return
// } // }
if (binding.tvPaymentDate.text.toString() == "Pilih tanggal") { // if (binding.tvPaymentDate.text.toString() == "Pilih tanggal") {
Toast.makeText(this, "Silahkan pilih tanggal pembayaran", Toast.LENGTH_SHORT).show() // Toast.makeText(this, "Silahkan pilih tanggal pembayaran", Toast.LENGTH_SHORT).show()
return // return
} // }
// All validations passed, proceed with upload // All validations passed, proceed with upload
uploadPaymentProof() uploadPaymentProof()

View File

@ -547,15 +547,6 @@ class OrderHistoryAdapter(
// Use ViewModel to fetch order details // Use ViewModel to fetch order details
viewModel.getOrderDetails(order.orderId) viewModel.getOrderDetails(order.orderId)
// Create loading dialog
// val loadingDialog = Dialog(itemView.context).apply {
// requestWindowFeature(Window.FEATURE_NO_TITLE)
// setContentView(R.layout.dialog_loading)
// window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
// setCancelable(false)
// }
// loadingDialog.show()
viewModel.error.observe(itemView.findViewTreeLifecycleOwner()!!) { errorMsg -> viewModel.error.observe(itemView.findViewTreeLifecycleOwner()!!) { errorMsg ->
if (!errorMsg.isNullOrEmpty()) { if (!errorMsg.isNullOrEmpty()) {
Toast.makeText(itemView.context, errorMsg, Toast.LENGTH_SHORT).show() Toast.makeText(itemView.context, errorMsg, Toast.LENGTH_SHORT).show()

View File

@ -112,13 +112,17 @@ class DetailProductActivity : AppCompatActivity() {
when (result) { when (result) {
is Result.Success -> { is Result.Success -> {
updateStoreInfo(result.data) updateStoreInfo(result.data)
binding.progressBarDetailStore.visibility = View.GONE
} }
is Result.Error -> { is Result.Error -> {
// Show error message, maybe a Toast or Snackbar // Show error message, maybe a Toast or Snackbar
Toast.makeText(this, "Failed to load store: ${result.exception.message}", Toast.LENGTH_SHORT).show() binding.progressBarDetailStore.visibility = View.GONE
Log.e("DetailProfileActivity", "Failed to load store: ${result.exception.message}")
Toast.makeText(this, "Kendala memuat toko", Toast.LENGTH_SHORT).show()
} }
is Result.Loading -> { is Result.Loading -> {
// Show loading indicator if needed // Show loading indicator if needed
binding.progressBarDetailStore.visibility = View.VISIBLE
} }
} }
} }
@ -160,6 +164,10 @@ class DetailProductActivity : AppCompatActivity() {
val products = viewModel.otherProducts.value.orEmpty() val products = viewModel.otherProducts.value.orEmpty()
if (products.isNotEmpty()) { if (products.isNotEmpty()) {
updateOtherProducts(products, storeMap) updateOtherProducts(products, storeMap)
} else {
binding.emptyOtherProducts.visibility = View.VISIBLE
binding.recyclerViewOtherProducts.visibility = View.GONE
binding.tvViewAllProducts.visibility = View.GONE
} }
} }
} }
@ -190,12 +198,14 @@ class DetailProductActivity : AppCompatActivity() {
private fun updateOtherProducts(products: List<ProductsItem>, storeMap: Map<Int, StoreItem>) { private fun updateOtherProducts(products: List<ProductsItem>, storeMap: Map<Int, StoreItem>) {
if (products.isEmpty()) { if (products.isEmpty()) {
Log.d("DetailProductActivity", "Product list is empty, hiding RecyclerView") Log.d("DetailProductActivity", "Product list is empty, hiding RecyclerView")
binding.recyclerViewOtherProducts.visibility = View.VISIBLE binding.recyclerViewOtherProducts.visibility = View.GONE
binding.emptyOtherProducts.visibility = View.VISIBLE
binding.tvViewAllProducts.visibility = View.GONE binding.tvViewAllProducts.visibility = View.GONE
} else { } else {
Log.d("DetailProductActivity", "Displaying product list in RecyclerView") Log.d("DetailProductActivity", "Displaying product list in RecyclerView")
binding.recyclerViewOtherProducts.visibility = View.VISIBLE binding.recyclerViewOtherProducts.visibility = View.VISIBLE
binding.tvViewAllProducts.visibility = View.VISIBLE binding.tvViewAllProducts.visibility = View.VISIBLE
binding.emptyOtherProducts.visibility = View.GONE
productAdapter = OtherProductAdapter(products, onClick = { product -> productAdapter = OtherProductAdapter(products, onClick = { product ->
handleProductClick(product) handleProductClick(product)
@ -316,11 +326,13 @@ class DetailProductActivity : AppCompatActivity() {
val limitedReviewList = if (reviewList.isNotEmpty()) listOf(reviewList.first()) else emptyList() val limitedReviewList = if (reviewList.isNotEmpty()) listOf(reviewList.first()) else emptyList()
if (reviewList.isEmpty()) { if (reviewList.isEmpty()) {
binding.recyclerViewReviews.visibility = View.GONE binding.recyclerViewReviews.visibility = View.GONE
binding.emptyReview.visibility = View.VISIBLE
binding.tvViewAllReviews.visibility = View.GONE binding.tvViewAllReviews.visibility = View.GONE
// binding.tvNoReviews.visibility = View.VISIBLE // binding.tvNoReviews.visibility = View.VISIBLE
} else { } else {
binding.recyclerViewReviews.visibility = View.VISIBLE binding.recyclerViewReviews.visibility = View.VISIBLE
binding.tvViewAllReviews.visibility = View.VISIBLE binding.tvViewAllReviews.visibility = View.VISIBLE
binding.emptyReview.visibility = View.GONE
} }
// binding.tvNoReviews.visibility = View.GONE // binding.tvNoReviews.visibility = View.GONE
reviewsAdapter = ReviewsAdapter( reviewsAdapter = ReviewsAdapter(
@ -519,7 +531,11 @@ class DetailProductActivity : AppCompatActivity() {
attachProduct = true // This will auto-attach the product! attachProduct = true // This will auto-attach the product!
) )
}
override fun onResume() {
super.onResume()
loadData()
} }
companion object { companion object {

View File

@ -64,10 +64,9 @@ class StoreDetailActivity : AppCompatActivity() {
) )
windowInsets windowInsets
} }
loadData()
setupUI() setupUI()
setupObservers() setupObservers()
loadData()
} }
private fun setupUI() { private fun setupUI() {
@ -88,15 +87,18 @@ class StoreDetailActivity : AppCompatActivity() {
viewModel.storeDetail.observe(this) { result -> viewModel.storeDetail.observe(this) { result ->
when (result) { when (result) {
is Result.Success -> { is Result.Success -> {
binding.progressBarDetailProdItem.visibility = View.GONE
updateStoreInfo(result.data) updateStoreInfo(result.data)
viewModel.loadOtherProducts(result.data.storeId) viewModel.loadOtherProducts(result.data.storeId)
} }
is Result.Error -> { is Result.Error -> {
// Show error message, maybe a Toast or Snackbar // Show error message, maybe a Toast or Snackbar
binding.progressBarDetailProdItem.visibility = View.GONE
Toast.makeText(this, "Failed to load store: ${result.exception.message}", Toast.LENGTH_SHORT).show() Toast.makeText(this, "Failed to load store: ${result.exception.message}", Toast.LENGTH_SHORT).show()
} }
is Result.Loading -> { is Result.Loading -> {
// Show loading indicator if needed // Show loading indicator if needed
binding.progressBarDetailProdItem.visibility = View.VISIBLE
} }
} }
} }
@ -109,6 +111,9 @@ class StoreDetailActivity : AppCompatActivity() {
val products = viewModel.otherProducts.value.orEmpty() val products = viewModel.otherProducts.value.orEmpty()
if (products.isNotEmpty()) { if (products.isNotEmpty()) {
updateProducts(products, storeMap) updateProducts(products, storeMap)
} else {
binding.progressBarDetailProdItem.visibility = View.VISIBLE
binding.rvProducts.visibility = View.GONE
} }
} }
} }
@ -146,7 +151,7 @@ class StoreDetailActivity : AppCompatActivity() {
.into(binding.ivStoreImage) .into(binding.ivStoreImage)
val ratingStr = it.storeRating val ratingStr = it.storeRating
val ratingValue = ratingStr?.toFloatOrNull() val ratingValue = ratingStr.toFloatOrNull()
if (ratingValue != null && ratingValue > 0f) { if (ratingValue != null && ratingValue > 0f) {
binding.tvStoreRating.text = String.format("%.1f", ratingValue) binding.tvStoreRating.text = String.format("%.1f", ratingValue)
@ -161,10 +166,12 @@ class StoreDetailActivity : AppCompatActivity() {
private fun updateProducts(products: List<ProductsItem>, storeMap: Map<Int, StoreItem>) { private fun updateProducts(products: List<ProductsItem>, storeMap: Map<Int, StoreItem>) {
if (products.isEmpty()) { if (products.isEmpty()) {
binding.rvProducts.visibility = View.GONE binding.rvProducts.visibility = View.GONE
binding.progressBarDetailProdItem.visibility = View.VISIBLE
Log.d("StoreDetailActivity", "Product list is empty, hiding RecyclerView") Log.d("StoreDetailActivity", "Product list is empty, hiding RecyclerView")
} else { } else {
Log.d("StoreDetailActivity", "Displaying product list in RecyclerView") Log.d("StoreDetailActivity", "Displaying product list in RecyclerView")
binding.progressBarDetailProdItem.visibility = View.GONE
binding.rvProducts.visibility = View.VISIBLE binding.rvProducts.visibility = View.VISIBLE
productAdapter = HorizontalProductAdapter(products, onClick = { product -> productAdapter = HorizontalProductAdapter(products, onClick = { product ->
handleProductClick(product) handleProductClick(product)

View File

@ -90,6 +90,8 @@ class DetailProfileActivity : AppCompatActivity() {
Log.e("DetailProfileActivity", "Error from ViewModel: $error") Log.e("DetailProfileActivity", "Error from ViewModel: $error")
Toast.makeText(this, error, Toast.LENGTH_SHORT).show() Toast.makeText(this, error, Toast.LENGTH_SHORT).show()
} }
} }
private fun setupClickListeners() { private fun setupClickListeners() {

View File

@ -95,12 +95,14 @@ class ProfileFragment : Fragment() {
binding.cardLogout.visibility = View.GONE binding.cardLogout.visibility = View.GONE
} }
viewModel.loadUserProfile()
viewModel.checkStoreUser()
observeUserProfile() observeUserProfile()
observeStoreStatus() observeStoreStatus()
viewModel.loadUserProfile()
viewModel.checkStoreUser()
binding.cardBukaToko.setOnClickListener{ binding.cardBukaToko.setOnClickListener{
// if (hasStore == true) startActivity(Intent(requireContext(), MyStoreActivity::class.java)) // if (hasStore == true) startActivity(Intent(requireContext(), MyStoreActivity::class.java))
@ -232,4 +234,11 @@ class ProfileFragment : Fragment() {
} }
} }
override fun onResume() {
super.onResume()
viewModel.loadUserProfile()
viewModel.checkStoreUser()
}
} }

View File

@ -2,6 +2,7 @@ package com.alya.ecommerce_serang.ui.profile.editprofile
import android.Manifest import android.Manifest
import android.app.Activity import android.app.Activity
import android.app.AlertDialog
import android.app.DatePickerDialog import android.app.DatePickerDialog
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
@ -24,7 +25,6 @@ import com.alya.ecommerce_serang.BuildConfig.BASE_URL
import com.alya.ecommerce_serang.R import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.data.api.dto.UserProfile import com.alya.ecommerce_serang.data.api.dto.UserProfile
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig 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.Result import com.alya.ecommerce_serang.data.repository.Result
import com.alya.ecommerce_serang.data.repository.UserRepository import com.alya.ecommerce_serang.data.repository.UserRepository
import com.alya.ecommerce_serang.databinding.ActivityEditProfileCustBinding import com.alya.ecommerce_serang.databinding.ActivityEditProfileCustBinding
@ -33,7 +33,6 @@ import com.alya.ecommerce_serang.utils.SessionManager
import com.alya.ecommerce_serang.utils.viewmodel.ProfileViewModel import com.alya.ecommerce_serang.utils.viewmodel.ProfileViewModel
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.google.gson.Gson import com.google.gson.Gson
import java.io.File
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Locale import java.util.Locale
@ -41,9 +40,9 @@ import java.util.TimeZone
class EditProfileCustActivity : AppCompatActivity() { class EditProfileCustActivity : AppCompatActivity() {
private lateinit var binding: ActivityEditProfileCustBinding private lateinit var binding: ActivityEditProfileCustBinding
private lateinit var apiService: ApiService
private lateinit var sessionManager: SessionManager private lateinit var sessionManager: SessionManager
private var selectedImageUri: Uri? = null private var selectedImageUri: Uri? = null
private var currentUser: UserProfile? = null
private val viewModel: ProfileViewModel by viewModels { private val viewModel: ProfileViewModel by viewModels {
BaseViewModelFactory { BaseViewModelFactory {
@ -54,7 +53,7 @@ class EditProfileCustActivity : AppCompatActivity() {
} }
private val getContent = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> private val getContent = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) { if (result.resultCode == RESULT_OK) {
val data: Intent? = result.data val data: Intent? = result.data
data?.data?.let { data?.data?.let {
selectedImageUri = it selectedImageUri = it
@ -105,8 +104,8 @@ class EditProfileCustActivity : AppCompatActivity() {
} }
userProfile?.let { userProfile?.let {
currentUser = it
populateFields(it) populateFields(it)
setupClickListeners() setupClickListeners()
observeViewModel() observeViewModel()
} }
@ -118,7 +117,7 @@ class EditProfileCustActivity : AppCompatActivity() {
binding.etNumberPhoneUser.setText(profile.phone) binding.etNumberPhoneUser.setText(profile.phone)
// Format birth date for display // Format birth date for display
profile.birthDate?.let { profile.birthDate.let {
binding.etDateBirth.setText(formatDate(it)) binding.etDateBirth.setText(formatDate(it))
} }
@ -156,7 +155,7 @@ class EditProfileCustActivity : AppCompatActivity() {
} }
binding.btnSave.setOnClickListener { binding.btnSave.setOnClickListener {
saveProfile() if (hasChanged()) confirmUpdate() else finish()
} }
} }
@ -213,25 +212,38 @@ class EditProfileCustActivity : AppCompatActivity() {
datePickerDialog.show() datePickerDialog.show()
} }
private fun confirmUpdate() {
AlertDialog.Builder(this)
.setTitle("Konfirmasi Perubahan")
.setMessage("Apakah Anda yakin ingin menyimpan perubahan profil toko Anda?")
.setPositiveButton("Ya") { _, _ -> saveProfile() }
.setNegativeButton("Batal", null)
.show()
}
private fun hasChanged(): Boolean {
val name = binding.etNameUser.text.toString() != currentUser?.name
val username = binding.etUsername.text.toString() != currentUser?.username
val email = binding.etEmailUser.text.toString() != currentUser?.email
val phone = binding.etNumberPhoneUser.text.toString() != currentUser?.phone
val displayDate = binding.etDateBirth.text.toString() != currentUser?.birthDate.toString()
val imgProfile = selectedImageUri != null
return name || username || email || phone || displayDate || imgProfile
}
private fun saveProfile() { private fun saveProfile() {
val name = binding.etNameUser.text.toString() val name = binding.etNameUser.text.toString()
val username = binding.etUsername.text.toString() val username = binding.etUsername.text.toString()
val email = binding.etEmailUser.text.toString() val email = binding.etEmailUser.text.toString()
val phone = binding.etNumberPhoneUser.text.toString() val phone = binding.etNumberPhoneUser.text.toString()
val displayDate = binding.etDateBirth.text.toString() val displayDate = binding.etDateBirth.text.toString()
val imgProfile = selectedImageUri
if (name.isEmpty() || username.isEmpty() || email.isEmpty() || phone.isEmpty() || displayDate.isEmpty()) {
Toast.makeText(this, "Semua field harus diisi", Toast.LENGTH_SHORT).show()
return
}
// Convert date to server format
val serverBirthDate = convertToServerDateFormat(displayDate) val serverBirthDate = convertToServerDateFormat(displayDate)
Log.d(TAG, "Starting profile save with direct method") Log.d(TAG, "Starting profile save with direct method")
Log.d(TAG, "Selected image URI: $selectedImageUri") Log.d(TAG, "Selected image URI: $selectedImageUri")
// Disable the button to prevent multiple clicks
binding.btnSave.isEnabled = false binding.btnSave.isEnabled = false
// Call the repository method via ViewModel // Call the repository method via ViewModel
@ -242,82 +254,10 @@ class EditProfileCustActivity : AppCompatActivity() {
phone = phone, phone = phone,
birthDate = serverBirthDate, birthDate = serverBirthDate,
email = email, email = email,
imageUri = selectedImageUri imageUri = imgProfile
) )
} }
private fun getRealPathFromURI(uri: Uri): String? {
Log.d(TAG, "Getting real path from URI: $uri")
// Handle different URI schemes
when {
// File URI
uri.scheme == "file" -> {
val path = uri.path
Log.d(TAG, "URI is file scheme, path: $path")
return path
}
// Content URI
uri.scheme == "content" -> {
try {
val projection = arrayOf(MediaStore.Images.Media.DATA)
contentResolver.query(uri, projection, null, null, null)?.use { cursor ->
if (cursor.moveToFirst()) {
val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
val path = cursor.getString(columnIndex)
Log.d(TAG, "Found path from content URI: $path")
return path
} else {
Log.e(TAG, "Cursor is empty")
}
} ?: Log.e(TAG, "Cursor is null")
// If the above fails, try the documented API way
contentResolver.openInputStream(uri)?.use { inputStream ->
// Create a temp file
val fileName = getFileName(uri) ?: "temp_img_${System.currentTimeMillis()}.jpg"
val tempFile = File(cacheDir, fileName)
tempFile.outputStream().use { outputStream ->
inputStream.copyTo(outputStream)
}
Log.d(TAG, "Created temporary file: ${tempFile.absolutePath}")
return tempFile.absolutePath
}
} catch (e: Exception) {
Log.e(TAG, "Error getting real path: ${e.message}", e)
}
}
}
Log.e(TAG, "Could not get real path for URI: $uri")
return null
}
private fun getFileName(uri: Uri): String? {
var result: String? = null
if (uri.scheme == "content") {
contentResolver.query(uri, null, null, null, null)?.use { cursor ->
if (cursor.moveToFirst()) {
val columnIndex = cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)
if (columnIndex >= 0) {
result = cursor.getString(columnIndex)
Log.d(TAG, "Found filename from content URI: $result")
}
}
}
}
if (result == null) {
result = uri.path
val cut = result?.lastIndexOf('/') ?: -1
if (cut != -1) {
result = result?.substring(cut + 1)
}
Log.d(TAG, "Extracted filename from path: $result")
}
return result
}
private fun formatDate(dateString: String?): String { private fun formatDate(dateString: String?): String {
if (dateString.isNullOrEmpty()) return "N/A" if (dateString.isNullOrEmpty()) return "N/A"

View File

@ -59,20 +59,20 @@ class MyStoreActivity : AppCompatActivity() {
finish() finish()
} }
viewModel.loadMyStore()
viewModel.loadMyStoreProducts()
viewModel.myStoreProfile.observe(this){ user -> viewModel.myStoreProfile.observe(this){ user ->
user?.let { myStoreProfileOverview(it.store) } user?.let { myStoreProfileOverview(it.store) }
} }
viewModel.loadMyStore()
viewModel.loadMyStoreProducts()
viewModel.fetchBalance()
viewModel.errorMessage.observe(this) { error -> viewModel.errorMessage.observe(this) { error ->
Toast.makeText(this, error, Toast.LENGTH_SHORT).show() Toast.makeText(this, error, Toast.LENGTH_SHORT).show()
} }
setUpClickListeners() setUpClickListeners()
getCountOrder() getCountOrder()
observeViewModel() observeViewModel()
viewModel.fetchBalance()
fetchBalance() fetchBalance()
} }
@ -206,6 +206,13 @@ class MyStoreActivity : AppCompatActivity() {
} }
} }
override fun onResume() {
super.onResume()
viewModel.loadMyStore()
viewModel.loadMyStoreProducts()
viewModel.fetchBalance()
}
companion object { companion object {
private const val PROFILE_REQUEST_CODE = 100 private const val PROFILE_REQUEST_CODE = 100
} }

View File

@ -97,7 +97,7 @@ class SellsAdapter(
val product = order.orderItems?.firstOrNull() val product = order.orderItems?.firstOrNull()
tvSellsProductName.text = product?.productName tvSellsProductName.text = product?.productName
tvSellsProductQty.text = "x${product?.quantity}" tvSellsProductQty.text = "x${product?.quantity}"
tvSellsProductPrice.text = product?.price?.let { formatPrice(it.toInt()) } tvSellsProductPrice.text = product?.price?.let { formatPrice(it.toDouble().toInt()) }
val fullImageUrl = when (val img = product?.productImage) { val fullImageUrl = when (val img = product?.productImage) {
is String -> { is String -> {
@ -170,7 +170,7 @@ class SellsAdapter(
val product = order.orderItems?.firstOrNull() val product = order.orderItems?.firstOrNull()
tvSellsProductName.text = product?.productName tvSellsProductName.text = product?.productName
tvSellsProductQty.text = "x${product?.quantity}" tvSellsProductQty.text = "x${product?.quantity}"
tvSellsProductPrice.text = product?.price?.let { formatPrice(it.toInt()) } tvSellsProductPrice.text = product?.price?.let { formatPrice(it.toDouble().toInt()) }
val fullImageUrl = when (val img = product?.productImage) { val fullImageUrl = when (val img = product?.productImage) {
is String -> { is String -> {
@ -186,7 +186,7 @@ class SellsAdapter(
.into(ivSellsProduct) .into(ivSellsProduct)
tvSellsQty.text = "${order.orderItems?.size} produk" tvSellsQty.text = "${order.orderItems?.size} produk"
tvSellsPrice.text = order.totalAmount?.let { formatPrice(it.toInt()) } tvSellsPrice.text = order.totalAmount?.let { formatPrice(it.toDouble().toInt()) }
} }
"paid" -> { "paid" -> {
layoutOrders.visibility = View.GONE layoutOrders.visibility = View.GONE

View File

@ -83,10 +83,10 @@ class SellsListFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
loadSells()
setupRecyclerView() setupRecyclerView()
observeSellsList() observeSellsList()
observePaymentConfirmation() observePaymentConfirmation()
loadSells()
// getAllOrderCountsAndNavigate() // getAllOrderCountsAndNavigate()
} }
@ -211,6 +211,12 @@ class SellsListFragment : Fragment() {
} }
} }
override fun onResume() {
super.onResume()
viewModel.getSellList(status)
observeSellsList()
}
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
_binding = null _binding = null

View File

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="100dp" android:tint="#489EC6" android:viewportHeight="24" android:viewportWidth="24" android:width="100dp">
<path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM12,6c1.93,0 3.5,1.57 3.5,3.5S13.93,13 12,13s-3.5,-1.57 -3.5,-3.5S10.07,6 12,6zM12,20c-2.03,0 -4.43,-0.82 -6.14,-2.88C7.55,15.8 9.68,15 12,15s4.45,0.8 6.14,2.12C16.43,19.18 14.03,20 12,20z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#489EC6" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M12,2C6.47,2 2,6.47 2,12s4.47,10 10,10 10,-4.47 10,-10S17.53,2 12,2z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#211E1E" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M7,18c-1.1,0 -1.99,0.9 -1.99,2S5.9,22 7,22s2,-0.9 2,-2 -0.9,-2 -2,-2zM1,2v2h2l3.6,7.59 -1.35,2.45c-0.16,0.28 -0.25,0.61 -0.25,0.96 0,1.1 0.9,2 2,2h12v-2L7.42,15c-0.14,0 -0.25,-0.11 -0.25,-0.25l0.03,-0.12 0.9,-1.63h7.45c0.75,0 1.41,-0.41 1.75,-1.03l3.58,-6.49c0.08,-0.14 0.12,-0.31 0.12,-0.48 0,-0.55 -0.45,-1 -1,-1L5.21,4l-0.94,-2L1,2zM17,18c-1.1,0 -1.99,0.9 -1.99,2s0.89,2 1.99,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#211E1E" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M20,4L4,4c-1.11,0 -1.99,0.89 -1.99,2L2,18c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2L22,6c0,-1.11 -0.89,-2 -2,-2zM20,18L4,18v-6h16v6zM20,8L4,8L4,6h16v2z"/>
</vector>

View File

@ -3,6 +3,6 @@
android:shape="rectangle"> android:shape="rectangle">
<solid android:color="@color/blue_500" /> <solid android:color="@color/blue_500" />
<corners android:radius="5dp" /> <corners android:radius="24dp" />
</shape> </shape>

View File

@ -113,6 +113,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:visibility="gone"
android:text="Metode Pembayaran *" android:text="Metode Pembayaran *"
android:fontFamily="@font/dmsans_semibold" android:fontFamily="@font/dmsans_semibold"
android:textSize="16sp" /> android:textSize="16sp" />
@ -122,6 +123,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:visibility="gone"
android:background="@drawable/edit_text_background" android:background="@drawable/edit_text_background"
android:minHeight="50dp" android:minHeight="50dp"
android:padding="12dp" /> android:padding="12dp" />

View File

@ -34,69 +34,50 @@
android:orientation="vertical"> android:orientation="vertical">
<!-- Delivery Address Section --> <!-- Delivery Address Section -->
<androidx.cardview.widget.CardView <com.google.android.material.card.MaterialCardView
android:id="@+id/card_delivery_address" android:id="@+id/card_delivery_address"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="0dp" android:layout_marginHorizontal="16dp"
android:layout_marginTop="0dp" android:layout_marginTop="16dp"
app:cardElevation="0dp"> app:cardCornerRadius="12dp"
app:cardElevation="2dp"
app:cardBackgroundColor="@color/white"
app:strokeColor="#E0E0E0"
app:strokeWidth="1dp">
<LinearLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:padding="20dp">
android:padding="16dp"
android:background="@color/white">
<!-- Header Row -->
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:id="@+id/address_header"
android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:gravity="center_vertical"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<ImageView <ImageView
android:id="@+id/iv_location_icon" android:id="@+id/iv_location_icon"
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
android:src="@drawable/baseline_location_pin_24" android:src="@drawable/baseline_location_pin_24"
android:layout_gravity="center_vertical" app:tint="@color/blue_300" />
app:tint="#3D84FF" />
<TextView <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Alamat Pengiriman"
android:textSize="16sp"
android:fontFamily="@font/dmsans_medium"
android:layout_marginStart="8dp" />
</LinearLayout>
<TextView
android:id="@+id/tv_places_address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-"
android:textColor="#5A5A5A"
android:paddingHorizontal="8dp"
android:paddingVertical="2dp"
android:textSize="12sp"
android:layout_marginTop="8dp"
android:layout_marginStart="32dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="8dp">
<TextView
android:id="@+id/tv_address"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:text="-" android:text="Alamat Pengiriman"
android:textSize="14sp" android:textSize="16sp"
android:layout_marginStart="32dp" /> android:textColor="@android:color/black"
android:fontFamily="@font/dmsans_medium"
android:layout_marginStart="12dp" />
<TextView <TextView
android:id="@+id/tv_change_address" android:id="@+id/tv_change_address"
@ -104,178 +85,441 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Pilih Alamat" android:text="Pilih Alamat"
android:textColor="#3D84FF" android:textColor="#3D84FF"
android:textSize="14sp" /> android:textSize="14sp"
android:fontFamily="@font/dmsans_medium"
android:background="?attr/selectableItemBackgroundBorderless"
android:paddingHorizontal="8dp"
android:paddingVertical="4dp" />
</LinearLayout> </LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
<View <!-- Empty Address State -->
android:layout_width="match_parent" <LinearLayout
android:layout_height="8dp" android:id="@+id/container_empty_address"
android:background="@color/black_50" /> android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="4dp"
android:gravity="center"
android:padding="8dp"
app:layout_constraintTop_toBottomOf="@id/address_header"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="Belum ada alamat dipilih"
android:fontFamily="@font/dmsans_medium"
android:textColor="#757575"
android:textSize="14sp"
android:gravity="center" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="Pilih alamat pengiriman untuk melanjutkan"
android:textColor="#BDBDBD"
android:textSize="12sp"
android:gravity="center" />
</LinearLayout>
<!-- Selected Address Content -->
<LinearLayout
android:id="@+id/container_address"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="4dp"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/address_header"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<!-- Address Label -->
<TextView
android:id="@+id/tv_places_address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Rumah"
android:textColor="#3D84FF"
android:textSize="12sp"
android:fontFamily="@font/dmsans_medium"
android:background="@drawable/bg_edit_text_background"
android:paddingHorizontal="8dp"
android:paddingVertical="4dp"
tools:text="Rumah" />
<!-- Full Address -->
<TextView
android:id="@+id/tv_address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Jl. Raya Serang No. 123, Kecamatan Serang, Kabupaten Serang, Banten 42111"
android:textSize="14sp"
android:textColor="@android:color/black"
android:lineSpacingExtra="2dp"
tools:text="Jl. Raya Serang No. 123, Kecamatan Serang, Kabupaten Serang, Banten 42111" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Product Items Section --> <!-- Product Items Section -->
<androidx.cardview.widget.CardView <com.google.android.material.card.MaterialCardView
android:id="@+id/card_product" android:id="@+id/card_product"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:cardElevation="0dp"> android:layout_marginHorizontal="16dp"
android:layout_marginTop="8dp"
app:cardBackgroundColor="@color/white"
app:strokeColor="#E0E0E0"
app:strokeWidth="1dp">
<LinearLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:padding="20dp">
android:background="@color/white"
android:padding="16dp">
<androidx.recyclerview.widget.RecyclerView <!-- Header Row -->
android:id="@+id/rv_product_items" <LinearLayout
android:layout_width="match_parent" android:id="@+id/product_header"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
tools:listitem="@layout/item_order_seller" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<View
android:layout_width="match_parent"
android:layout_height="8dp"
android:background="#F5F5F5" />
<View
android:layout_width="match_parent"
android:layout_height="8dp"
android:background="@color/black_50" />
<!-- Shipping Method Section -->
<LinearLayout
android:id="@+id/layout_shipping_method"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@color/white"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
<TextView
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Metode Pengiriman"
android:textSize="14sp" />
<TextView
android:id="@+id/tv_shipping_option"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Opsi Pengiriman"
android:textColor="#3D84FF"
android:textSize="14sp" />
</LinearLayout>
<androidx.cardview.widget.CardView
android:id="@+id/card_shipment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:visibility="gone"
app:cardCornerRadius="8dp"
app:cardElevation="0dp"
app:cardBackgroundColor="#F5F5F5">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="12dp"> android:gravity="center_vertical"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<RadioButton <ImageView
android:id="@+id/rb_jne" android:layout_width="24dp"
android:layout_width="wrap_content" android:layout_height="24dp"
android:layout_height="wrap_content" android:src="@drawable/baseline_local_grocery_store_24"
android:checked="true" /> app:tint="@color/blue_300" />
<LinearLayout <TextView
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:orientation="vertical" android:text="Produk Pesanan"
android:layout_marginStart="8dp"> android:textSize="16sp"
android:textColor="@android:color/black"
android:fontFamily="@font/dmsans_medium"
android:layout_marginStart="12dp" />
</LinearLayout>
<TextView <!-- Empty Product State -->
android:id="@+id/tv_courier_name" <LinearLayout
android:layout_width="wrap_content" android:id="@+id/container_empty_products"
android:layout_height="wrap_content" android:layout_width="0dp"
android:text="JNE" android:layout_height="wrap_content"
android:textSize="16sp" android:orientation="vertical"
android:fontFamily="@font/dmsans_medium" /> android:layout_marginTop="4dp"
android:gravity="center"
android:padding="8dp"
android:visibility="visible"
app:layout_constraintTop_toBottomOf="@id/product_header"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<TextView
android:id="@+id/tv_delivery_estimate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="3 - 4 hari kerja"
android:textSize="14sp"
android:textColor="#757575" />
</LinearLayout>
<TextView <TextView
android:id="@+id/tv_shipping_price"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Rp15.000" android:layout_marginTop="4dp"
android:textSize="16sp" android:text="Tidak ada produk"
android:fontFamily="@font/dmsans_medium" android:fontFamily="@font/dmsans_medium"
android:layout_gravity="center_vertical" /> android:textColor="#757575"
android:textSize="14sp"
android:gravity="center" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="Keranjang belanja kosong"
android:textColor="#BDBDBD"
android:textSize="12sp"
android:gravity="center" />
</LinearLayout> </LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
<View <!-- Products RecyclerView -->
android:layout_width="match_parent" <androidx.recyclerview.widget.RecyclerView
android:layout_height="8dp" android:id="@+id/rv_product_items"
android:background="@color/black_50" /> android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/product_header"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:listitem="@layout/item_order_seller" />
<!-- Payment Method Section --> </androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout </com.google.android.material.card.MaterialCardView>
android:id="@+id/layout_payment_method"
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_shipping_method"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:layout_marginHorizontal="16dp"
android:background="@color/white" android:layout_marginTop="8dp"
android:padding="16dp"> app:cardBackgroundColor="@color/white"
app:strokeColor="#E0E0E0"
app:strokeWidth="1dp">
<TextView <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Metode Pembayaran" android:padding="20dp">
android:textSize="14sp"
android:layout_marginBottom="8dp" />
<TextView <!-- Header Row -->
android:id="@+id/tvEmptyPayment" <LinearLayout
android:id="@+id/shipping_header"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Metode Pengiriman"
android:textSize="16sp"
android:textColor="@android:color/black"
android:fontFamily="@font/dmsans_medium"
android:layout_marginStart="12dp" />
<TextView
android:id="@+id/tv_shipping_option"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Pilih"
android:textColor="#3D84FF"
android:textSize="14sp"
android:fontFamily="@font/dmsans_medium"
android:background="?attr/selectableItemBackgroundBorderless"
android:paddingHorizontal="8dp"
android:paddingVertical="4dp" />
</LinearLayout>
<!-- Empty Shipping State -->
<LinearLayout
android:id="@+id/container_empty_shipping"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="4dp"
android:gravity="center"
android:padding="12dp"
app:layout_constraintTop_toBottomOf="@id/shipping_header"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="Belum ada metode pengiriman"
android:fontFamily="@font/dmsans_medium"
android:textColor="#757575"
android:textSize="14sp"
android:gravity="center" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="Pilih alamat terlebih dahulu"
android:textColor="#BDBDBD"
android:textSize="12sp"
android:gravity="center" />
</LinearLayout>
<!-- Selected Shipping Content -->
<androidx.cardview.widget.CardView
android:id="@+id/card_shipment"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:visibility="gone"
app:cardCornerRadius="8dp"
app:cardElevation="0dp"
app:cardBackgroundColor="#F5F5F5"
app:layout_constraintTop_toBottomOf="@id/shipping_header"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="12dp">
<RadioButton
android:id="@+id/rb_jne"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:layout_marginStart="8dp">
<TextView
android:id="@+id/tv_courier_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="JNE"
android:textSize="16sp"
android:fontFamily="@font/dmsans_medium" />
<TextView
android:id="@+id/tv_delivery_estimate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="3 - 4 hari kerja"
android:textSize="14sp"
android:textColor="#757575" />
</LinearLayout>
<TextView
android:id="@+id/tv_shipping_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Rp15.000"
android:textSize="16sp"
android:fontFamily="@font/dmsans_medium"
android:layout_gravity="center_vertical" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Payment Method Section -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_payment_method"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="8dp"
app:cardBackgroundColor="@color/white"
app:strokeColor="#E0E0E0"
app:strokeWidth="1dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="gone" android:padding="20dp">
android:textSize="12sp"
android:text="Pilih alamat terlebih dahulu"
android:layout_marginBottom="8dp"/>
<androidx.recyclerview.widget.RecyclerView <!-- Header Row -->
android:id="@+id/rv_payment_info" <LinearLayout
android:layout_width="match_parent" android:id="@+id/payment_header"
android:layout_height="wrap_content" android:layout_width="0dp"
tools:listitem="@layout/item_payment_method" /> android:layout_height="wrap_content"
</LinearLayout> android:orientation="horizontal"
android:gravity="center_vertical"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/baseline_payment_24"
app:tint="@color/blue_300" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Metode Pembayaran"
android:textSize="16sp"
android:textColor="@android:color/black"
android:fontFamily="@font/dmsans_medium"
android:layout_marginStart="12dp" />
<TextView
android:id="@+id/tv_payment_option"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Pilih"
android:textColor="#3D84FF"
android:textSize="14sp"
android:fontFamily="@font/dmsans_medium"
android:background="?attr/selectableItemBackgroundBorderless"
android:paddingHorizontal="8dp"
android:paddingVertical="4dp"
android:visibility="gone" />
</LinearLayout>
<!-- Empty Payment State -->
<LinearLayout
android:id="@+id/container_empty_payment"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="4dp"
android:gravity="center"
android:padding="12dp"
app:layout_constraintTop_toBottomOf="@id/payment_header"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="Belum ada metode pembayaran"
android:fontFamily="@font/dmsans_medium"
android:textColor="#757575"
android:textSize="14sp"
android:gravity="center" />
<TextView
android:id="@+id/tvEmptyPayment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="Pilih alamat terlebih dahulu"
android:textColor="#BDBDBD"
android:textSize="12sp"
android:gravity="center" />
</LinearLayout>
<!-- Payment Methods RecyclerView -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_payment_info"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/payment_header"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:listitem="@layout/item_payment_method" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="8dp" android:layout_height="8dp"
android:layout_marginVertical="8dp"
android:background="@color/black_50" /> android:background="@color/black_50" />
<!-- Price Summary Section --> <!-- Price Summary Section -->
@ -303,7 +547,7 @@
android:id="@+id/tv_item_total" android:id="@+id/tv_item_total"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Rp65.000" android:text="Rp0"
android:textSize="14sp" /> android:textSize="14sp" />
</LinearLayout> </LinearLayout>
@ -324,7 +568,7 @@
android:id="@+id/tv_shipping_fee" android:id="@+id/tv_shipping_fee"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Rp15.000" android:text="Rp0"
android:textSize="14sp" /> android:textSize="14sp" />
</LinearLayout> </LinearLayout>
@ -351,8 +595,8 @@
android:id="@+id/tv_total" android:id="@+id/tv_total"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Rp75.000" android:text="Rp0"
android:textColor="#3D84FF" android:textColor="@color/blue_400"
android:textSize="16sp" android:textSize="16sp"
android:fontFamily="@font/dmsans_bold" /> android:fontFamily="@font/dmsans_bold" />
</LinearLayout> </LinearLayout>
@ -388,7 +632,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Rp75.000" android:text="Rp75.000"
android:textColor="#3D84FF" android:textColor="@color/blue_400"
android:textSize="18sp" android:textSize="18sp"
android:fontFamily="@font/dmsans_bold" /> android:fontFamily="@font/dmsans_bold" />
</LinearLayout> </LinearLayout>
@ -401,7 +645,7 @@
android:textAllCaps="false" android:textAllCaps="false"
android:paddingHorizontal="32dp" android:paddingHorizontal="32dp"
app:cornerRadius="8dp" app:cornerRadius="8dp"
android:backgroundTint="#3D84FF" /> android:backgroundTint="@color/blue_500" />
</LinearLayout> </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -231,6 +231,18 @@
android:textSize="14sp" /> android:textSize="14sp" />
</LinearLayout> </LinearLayout>
<TextView
android:id="@+id/empty_review"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Belum ada ulasan"
android:textSize="16sp"
android:textColor="@color/black_200"
android:gravity="center"
android:visibility="gone"
android:fontFamily="@font/dmsans_mediumitalic"
android:layout_marginTop="8dp"/>
<!-- RecyclerView for Reviews --> <!-- RecyclerView for Reviews -->
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerViewReviews" android:id="@+id/recyclerViewReviews"
@ -385,6 +397,13 @@
android:orientation="horizontal" android:orientation="horizontal"
android:padding="16dp"> android:padding="16dp">
<ProgressBar
android:id="@+id/progress_bar_detail_store"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_gravity="center"/>
<de.hdodenhof.circleimageview.CircleImageView <de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/ivSellerImage" android:id="@+id/ivSellerImage"
android:layout_width="48dp" android:layout_width="48dp"
@ -477,6 +496,18 @@
android:textSize="14sp" /> android:textSize="14sp" />
</LinearLayout> </LinearLayout>
<TextView
android:id="@+id/empty_other_products"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Belum ada produk lainnya"
android:textSize="16sp"
android:textColor="@color/black_200"
android:gravity="center"
android:visibility="gone"
android:fontFamily="@font/dmsans_mediumitalic"
android:layout_marginTop="8dp"/>
<!-- RecyclerView for Other Products --> <!-- RecyclerView for Other Products -->
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerViewOtherProducts" android:id="@+id/recyclerViewOtherProducts"

View File

@ -62,7 +62,7 @@
android:id="@+id/profile_image" android:id="@+id/profile_image"
android:layout_width="100dp" android:layout_width="100dp"
android:layout_height="100dp" android:layout_height="100dp"
android:src="@drawable/baseline_account_circle_24" android:src="@drawable/baseline_account_circle_100"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/> app:layout_constraintEnd_toEndOf="parent"/>
@ -87,6 +87,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Ubah Profil" android:text="Ubah Profil"
style="@style/button.large.active.medium"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@id/profile_image" app:layout_constraintTop_toBottomOf="@id/profile_image"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"

View File

@ -61,7 +61,7 @@
android:id="@+id/profile_image" android:id="@+id/profile_image"
android:layout_width="100dp" android:layout_width="100dp"
android:layout_height="100dp" android:layout_height="100dp"
android:src="@drawable/baseline_account_circle_24" android:src="@drawable/baseline_account_circle_100"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/> app:layout_constraintEnd_toEndOf="parent"/>
@ -188,6 +188,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Simpan" android:text="Simpan"
style="@style/button.large.active.medium"
android:layout_marginTop="32dp" android:layout_marginTop="32dp"
android:layout_marginHorizontal="16dp" android:layout_marginHorizontal="16dp"
android:layout_marginBottom="16dp" android:layout_marginBottom="16dp"

View File

@ -15,156 +15,207 @@
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<!-- Store Information --> <!-- Store Information Card -->
<androidx.constraintlayout.widget.ConstraintLayout <com.google.android.material.card.MaterialCardView
android:id="@+id/storeInfoContainer" android:id="@+id/storeInfoCard"
android:layout_width="match_parent" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@color/blue_50" android:layout_marginStart="16dp"
android:layout_marginTop="16dp" android:layout_marginTop="20dp"
android:padding="24dp" android:layout_marginEnd="16dp"
app:cardBackgroundColor="@android:color/white"
app:cardCornerRadius="16dp"
app:cardElevation="4dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/searchContainer"> app:layout_constraintTop_toBottomOf="@id/searchContainer">
<ImageView <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ivStoreImage" android:id="@+id/storeInfoContainer"
android:layout_width="64dp" android:layout_width="match_parent"
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_height="wrap_content"
android:layout_marginStart="16dp" android:padding="24dp">
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 <!-- Store Image with Material Card wrapper -->
android:id="@+id/tvStoreType" <com.google.android.material.card.MaterialCardView
android:layout_width="0dp" android:id="@+id/storeImageCard"
android:layout_height="wrap_content" android:layout_width="80dp"
android:layout_marginStart="16dp" android:layout_height="80dp"
android:layout_marginEnd="16dp" app:cardCornerRadius="16dp"
android:textSize="14sp" app:cardElevation="2dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintStart_toEndOf="@id/ivStoreImage" app:layout_constraintTop_toTopOf="parent">
app:layout_constraintTop_toBottomOf="@id/tvStoreName"
tools:text="Makanan Ringan" />
<LinearLayout <ImageView
android:id="@+id/storeRatingContainer" android:id="@+id/ivStoreImage"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:layout_marginStart="16dp" android:scaleType="centerCrop"
android:layout_marginTop="4dp" tools:src="@drawable/placeholder_image" />
android:gravity="center_vertical" </com.google.android.material.card.MaterialCardView>
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" />
<!-- Store Name -->
<TextView <TextView
android:id="@+id/tvStoreRating" android:id="@+id/tvStoreName"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="4dp" android:layout_marginStart="20dp"
android:layout_marginEnd="16dp"
android:ellipsize="end"
android:maxLines="2"
android:textColor="@android:color/black"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/storeImageCard"
app:layout_constraintTop_toTopOf="@id/storeImageCard"
tools:text="SnackEnak Store" />
<!-- Store Type -->
<TextView
android:id="@+id/tvStoreType"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="16dp"
android:background="@drawable/search_background"
android:paddingStart="12dp"
android:paddingTop="4dp"
android:paddingEnd="12dp"
android:paddingBottom="4dp"
android:textColor="@color/blue_500"
android:textSize="12sp" android:textSize="12sp"
android:textStyle="bold" android:textStyle="bold"
tools:text="5.0" /> app:layout_constraintEnd_toEndOf="parent"
</LinearLayout> app:layout_constraintStart_toEndOf="@id/storeImageCard"
app:layout_constraintTop_toBottomOf="@id/tvStoreName"
tools:text="Makanan Ringan" />
<TextView <!-- Rating Container -->
android:id="@+id/tvStoreLocation" <LinearLayout
android:layout_width="0dp" android:id="@+id/storeRatingContainer"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:layout_marginStart="16dp" android:layout_height="wrap_content"
android:layout_marginTop="4dp" android:layout_marginStart="20dp"
android:layout_marginEnd="16dp" android:layout_marginTop="8dp"
android:textSize="12sp" android:gravity="center_vertical"
app:layout_constraintEnd_toStartOf="@id/tvActiveStatus" android:orientation="horizontal"
app:layout_constraintStart_toEndOf="@id/ivStoreImage" app:layout_constraintStart_toEndOf="@id/storeImageCard"
app:layout_constraintTop_toBottomOf="@id/storeRatingContainer" app:layout_constraintTop_toBottomOf="@id/tvStoreType">
tools:text="Kabupaten Serang" />
<TextView <ImageView
android:id="@+id/tvActiveStatus" android:id="@+id/ivStoreRatingStar"
android:layout_width="wrap_content" android:layout_width="16dp"
android:layout_height="wrap_content" android:layout_height="16dp"
android:paddingStart="4dp" android:src="@drawable/ic_star"
android:paddingEnd="4dp" app:tint="@color/yellow" />
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--> <TextView
<!-- android:id="@+id/btnChevron"--> android:id="@+id/tvStoreRating"
<!-- android:layout_width="wrap_content"--> android:layout_width="wrap_content"
<!-- android:layout_height="wrap_content"--> android:layout_height="wrap_content"
<!-- android:background="?attr/selectableItemBackgroundBorderless"--> android:layout_marginStart="4dp"
<!-- android:contentDescription="More"--> android:textColor="@android:color/black"
<!-- android:src="@drawable/ic_chevron_right"--> android:textSize="14sp"
<!-- app:layout_constraintBottom_toBottomOf="parent"--> android:textStyle="bold"
<!-- app:layout_constraintEnd_toEndOf="parent"--> tools:text="4.8" />
<!-- app:layout_constraintTop_toTopOf="parent" />--> </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- Location and Status Row -->
<LinearLayout
android:id="@+id/locationStatusContainer"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="16dp"
android:gravity="center_vertical"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/storeImageCard"
app:layout_constraintTop_toBottomOf="@id/storeRatingContainer">
<!-- Location with Icon -->
<ImageView
android:layout_width="14dp"
android:layout_height="14dp"
android:src="@drawable/ic_location"
app:tint="@color/black_300" />
<TextView
android:id="@+id/tvStoreLocation"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@color/blue_400"
android:textSize="13sp"
tools:text="Kabupaten Serang" />
<!-- Status Indicator -->
<View
android:id="@+id/statusDot"
android:layout_width="6dp"
android:layout_height="6dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="6dp"
android:background="@drawable/baseline_circle_24"
android:backgroundTint="@color/black_300"/>
<TextView
android:id="@+id/tvActiveStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/blue_500"
android:textSize="12sp"
android:fontFamily="@font/dmsans_semibold"
tools:text="Aktif" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Divider -->
<com.google.android.material.divider.MaterialDivider <com.google.android.material.divider.MaterialDivider
android:id="@+id/divider_product" android:id="@+id/divider_product"
android:layout_width="match_parent" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/storeInfoContainer"/> android:layout_marginTop="24dp"
app:dividerColor="@color/black_200"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/storeInfoCard" />
<ProgressBar
<!-- Tab Layout: TO DO implement after review --> android:id="@+id/progress_bar_detail_prod_item"
<!-- <com.google.android.material.tabs.TabLayout--> android:layout_width="wrap_content"
<!-- android:id="@+id/tabLayout"--> android:layout_height="wrap_content"
<!-- android:layout_width="match_parent"--> android:visibility="gone"
<!-- android:layout_height="wrap_content"--> android:layout_gravity="center"
<!-- app:layout_constraintTop_toBottomOf="@id/storeInfoContainer"--> app:layout_constraintBottom_toBottomOf="parent"
<!-- app:tabIndicatorColor="@color/colorPrimary"--> app:layout_constraintEnd_toEndOf="parent"
<!-- app:tabSelectedTextColor="@color/colorPrimary"--> app:layout_constraintStart_toStartOf="parent"
<!-- app:tabTextColor="@android:color/darker_gray">--> app:layout_constraintTop_toBottomOf="@id/divider_product"/>
<!-- <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 --> <!-- Products RecyclerView -->
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_products" android:id="@+id/rv_products"
android:layout_width="match_parent" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginTop="16dp" android:layout_marginStart="16dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp" android:layout_marginBottom="16dp"
android:clipToPadding="false"
android:paddingBottom="16dp"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/divider_product" app:layout_constraintTop_toBottomOf="@id/divider_product"
app:spanCount="2" app:spanCount="2"
tools:listitem="@layout/item_product_grid" /> tools:listitem="@layout/item_product_grid" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -168,8 +168,13 @@
app:layout_constraintTop_toBottomOf="@id/searchContainer" /> app:layout_constraintTop_toBottomOf="@id/searchContainer" />
<include <include
android:id="@+id/loading" android:id="@+id/loadingAll"
layout="@layout/view_loading"/> layout="@layout/view_loading"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<include <include
android:id="@+id/error" android:id="@+id/error"

View File

@ -71,7 +71,6 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
android:visibility="gone"
style="@style/Widget.Material3.Button.OutlinedButton.Icon" style="@style/Widget.Material3.Button.OutlinedButton.Icon"
android:text="Kembali" android:text="Kembali"
app:cornerRadius="8dp"/> app:cornerRadius="8dp"/>

View File

@ -9,10 +9,9 @@
android:id="@+id/content" android:id="@+id/content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="start" android:gravity="center"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginVertical="8dp" android:layout_marginVertical="8dp"
android:layout_marginBottom="4dp"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:orientation="horizontal"> android:orientation="horizontal">
<RadioButton <RadioButton
@ -24,38 +23,53 @@
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
<LinearLayout <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/courier_name_cost"
android:fontFamily="@font/dmsans_semibold"
android:textSize="20sp"
android:padding="4dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="JNE"/>
<TextView
android:id="@+id/est_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:paddingHorizontal="8dp"
android:text="Estimasi 3-4 hari"/>
</LinearLayout>
<TextView
android:id="@+id/cost_price"
android:textSize="16sp"
android:gravity="center_vertical"
android:layout_margin="16dp"
android:fontFamily="@font/dmsans_semibold"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:text="Rp15.0000"/> android:orientation="horizontal"
android:gravity="center_vertical"
android:weightSum="1">
<!-- Left Section -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.7"
android:orientation="vertical">
<TextView
android:id="@+id/courier_name_cost"
android:fontFamily="@font/dmsans_semibold"
android:textSize="14sp"
android:paddingHorizontal="2dp"
android:paddingTop="4dp"
android:ellipsize="end"
android:scrollHorizontally="false"
android:singleLine="false"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="2"
android:text="JNE Express"/>
<TextView
android:id="@+id/est_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp"
android:paddingHorizontal="4dp"
android:text="Estimasi 3-4 hari"/>
</LinearLayout>
<!-- Right Section -->
<TextView
android:id="@+id/cost_price"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.3"
android:textSize="14sp"
android:gravity="start"
android:fontFamily="@font/dmsans_semibold"
android:text="Rp15.000"/>
</LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -22,7 +22,8 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:text="Retry" android:text="Muat Ulang"
style="@style/Widget.Material3.FloatingActionButton.Large.Surface"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"

View File

@ -6,12 +6,13 @@
<ProgressBar <ProgressBar
android:id="@+id/progressBar" android:id="@+id/progressBar"
android:layout_width="24dp" android:layout_width="64dp"
android:layout_height="24dp" android:layout_height="64dp"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/> app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -269,7 +269,7 @@
</style> </style>
<style name="button.small.active.short"> <style name="button.small.active.short">
<item name="android:layout_width">144dp</item> <item name="android:layout_width">100dp</item>
</style> </style>
<style name="button.small.active.short.only_icon"> <style name="button.small.active.short.only_icon">