mirror of
https://github.com/shaulascr/ecommerce_serang.git
synced 2025-08-12 18:22:22 +00:00
update province cities subdistricts and villages
This commit is contained in:
@ -16,12 +16,12 @@ data class CreateAddressRequest (
|
|||||||
val subDistrict: String,
|
val subDistrict: String,
|
||||||
|
|
||||||
@SerializedName("city_id")
|
@SerializedName("city_id")
|
||||||
val cityId: Int,
|
val cityId: String,
|
||||||
|
|
||||||
@SerializedName("province_id")
|
@SerializedName("province_id")
|
||||||
val provId: Int,
|
val provId: Int,
|
||||||
@SerializedName("postal_code")
|
@SerializedName("postal_code")
|
||||||
val postCode: String? = null,
|
val postCode: String,
|
||||||
|
|
||||||
@SerializedName("detail")
|
@SerializedName("detail")
|
||||||
val detailAddress: String? = null,
|
val detailAddress: String? = null,
|
||||||
|
@ -12,10 +12,8 @@ data class ListProvinceResponse(
|
|||||||
)
|
)
|
||||||
|
|
||||||
data class ProvincesItem(
|
data class ProvincesItem(
|
||||||
|
|
||||||
@field:SerializedName("province")
|
|
||||||
val province: String,
|
|
||||||
|
|
||||||
@field:SerializedName("province_id")
|
@field:SerializedName("province_id")
|
||||||
val provinceId: String
|
val provinceId: String,
|
||||||
|
@field:SerializedName("province")
|
||||||
|
val province: String
|
||||||
)
|
)
|
||||||
|
@ -56,7 +56,7 @@ data class Orders(
|
|||||||
val orderItems: List<OrderListItemsItem>,
|
val orderItems: List<OrderListItemsItem>,
|
||||||
|
|
||||||
@field:SerializedName("auto_completed_at")
|
@field:SerializedName("auto_completed_at")
|
||||||
val autoCompletedAt: String? = null,
|
val autoCompletedAt: String,
|
||||||
|
|
||||||
@field:SerializedName("is_store_location")
|
@field:SerializedName("is_store_location")
|
||||||
val isStoreLocation: Boolean? = null,
|
val isStoreLocation: Boolean? = null,
|
||||||
|
@ -15,7 +15,7 @@ data class OrderListResponse(
|
|||||||
data class OrderItemsItem(
|
data class OrderItemsItem(
|
||||||
|
|
||||||
@field:SerializedName("review_id")
|
@field:SerializedName("review_id")
|
||||||
val reviewId: Int? = null,
|
val reviewId: Int,
|
||||||
|
|
||||||
@field:SerializedName("quantity")
|
@field:SerializedName("quantity")
|
||||||
val quantity: Int,
|
val quantity: Int,
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.alya.ecommerce_serang.data.api.response.customer.order
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
data class SubdistrictResponse(
|
||||||
|
|
||||||
|
@field:SerializedName("subdistricts")
|
||||||
|
val subdistricts: List<SubdistrictsItem>,
|
||||||
|
|
||||||
|
@field:SerializedName("message")
|
||||||
|
val message: String
|
||||||
|
)
|
||||||
|
|
||||||
|
data class SubdistrictsItem(
|
||||||
|
|
||||||
|
@field:SerializedName("subdistrict_id")
|
||||||
|
val subdistrictId: String,
|
||||||
|
|
||||||
|
@field:SerializedName("subdistrict_name")
|
||||||
|
val subdistrictName: String
|
||||||
|
)
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.alya.ecommerce_serang.data.api.response.customer.order
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
data class VillagesResponse(
|
||||||
|
|
||||||
|
@field:SerializedName("villages")
|
||||||
|
val villages: List<VillagesItem>,
|
||||||
|
|
||||||
|
@field:SerializedName("message")
|
||||||
|
val message: String
|
||||||
|
)
|
||||||
|
|
||||||
|
data class VillagesItem(
|
||||||
|
|
||||||
|
@field:SerializedName("village_id")
|
||||||
|
val villageId: String,
|
||||||
|
|
||||||
|
@field:SerializedName("village_name")
|
||||||
|
val villageName: String,
|
||||||
|
|
||||||
|
@field:SerializedName("postal_code")
|
||||||
|
val postalCode: String
|
||||||
|
)
|
@ -53,6 +53,8 @@ import com.alya.ecommerce_serang.data.api.response.customer.order.ListCityRespon
|
|||||||
import com.alya.ecommerce_serang.data.api.response.customer.order.ListProvinceResponse
|
import com.alya.ecommerce_serang.data.api.response.customer.order.ListProvinceResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.customer.order.OrderDetailResponse
|
import com.alya.ecommerce_serang.data.api.response.customer.order.OrderDetailResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.customer.order.OrderListResponse
|
import com.alya.ecommerce_serang.data.api.response.customer.order.OrderListResponse
|
||||||
|
import com.alya.ecommerce_serang.data.api.response.customer.order.SubdistrictResponse
|
||||||
|
import com.alya.ecommerce_serang.data.api.response.customer.order.VillagesResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.customer.product.AllProductResponse
|
import com.alya.ecommerce_serang.data.api.response.customer.product.AllProductResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.customer.product.CategoryResponse
|
import com.alya.ecommerce_serang.data.api.response.customer.product.CategoryResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.customer.product.DetailStoreProductResponse
|
import com.alya.ecommerce_serang.data.api.response.customer.product.DetailStoreProductResponse
|
||||||
@ -68,14 +70,14 @@ import com.alya.ecommerce_serang.data.api.response.order.ComplaintResponse
|
|||||||
import com.alya.ecommerce_serang.data.api.response.order.CompletedOrderResponse
|
import com.alya.ecommerce_serang.data.api.response.order.CompletedOrderResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.product.CreateSearchResponse
|
import com.alya.ecommerce_serang.data.api.response.product.CreateSearchResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.product.SearchHistoryResponse
|
import com.alya.ecommerce_serang.data.api.response.product.SearchHistoryResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.store.sells.PaymentConfirmationResponse
|
import com.alya.ecommerce_serang.data.api.response.store.GenericResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.store.product.CreateProductResponse
|
import com.alya.ecommerce_serang.data.api.response.store.product.CreateProductResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.store.product.DeleteProductResponse
|
import com.alya.ecommerce_serang.data.api.response.store.product.DeleteProductResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.store.product.UpdateProductResponse
|
import com.alya.ecommerce_serang.data.api.response.store.product.UpdateProductResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.store.product.ViewStoreProductsResponse
|
import com.alya.ecommerce_serang.data.api.response.store.product.ViewStoreProductsResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.store.GenericResponse
|
|
||||||
import com.alya.ecommerce_serang.data.api.response.store.profile.StoreDataResponse
|
import com.alya.ecommerce_serang.data.api.response.store.profile.StoreDataResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.store.review.ProductReviewResponse
|
import com.alya.ecommerce_serang.data.api.response.store.review.ProductReviewResponse
|
||||||
|
import com.alya.ecommerce_serang.data.api.response.store.sells.PaymentConfirmationResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.store.topup.BalanceTopUpResponse
|
import com.alya.ecommerce_serang.data.api.response.store.topup.BalanceTopUpResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.store.topup.TopUpResponse
|
import com.alya.ecommerce_serang.data.api.response.store.topup.TopUpResponse
|
||||||
import okhttp3.MultipartBody
|
import okhttp3.MultipartBody
|
||||||
@ -512,4 +514,14 @@ interface ApiService {
|
|||||||
@GET("store/reviews")
|
@GET("store/reviews")
|
||||||
suspend fun getStoreProductReview(
|
suspend fun getStoreProductReview(
|
||||||
): Response<ProductReviewResponse>
|
): Response<ProductReviewResponse>
|
||||||
|
|
||||||
|
@GET("subdistrict/{cityId}")
|
||||||
|
suspend fun getSubdistrict(
|
||||||
|
@Path("cityId") cityId: String
|
||||||
|
): Response<SubdistrictResponse>
|
||||||
|
|
||||||
|
@GET("villages/{subdistrictId}")
|
||||||
|
suspend fun getVillages(
|
||||||
|
@Path("subdistrictId") subdistrictId: String
|
||||||
|
): Response<VillagesResponse>
|
||||||
}
|
}
|
@ -21,6 +21,8 @@ import com.alya.ecommerce_serang.data.api.response.auth.RegisterStoreResponse
|
|||||||
import com.alya.ecommerce_serang.data.api.response.auth.VerifRegisterResponse
|
import com.alya.ecommerce_serang.data.api.response.auth.VerifRegisterResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.customer.order.ListCityResponse
|
import com.alya.ecommerce_serang.data.api.response.customer.order.ListCityResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.customer.order.ListProvinceResponse
|
import com.alya.ecommerce_serang.data.api.response.customer.order.ListProvinceResponse
|
||||||
|
import com.alya.ecommerce_serang.data.api.response.customer.order.SubdistrictResponse
|
||||||
|
import com.alya.ecommerce_serang.data.api.response.customer.order.VillagesResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.customer.profile.EditProfileResponse
|
import com.alya.ecommerce_serang.data.api.response.customer.profile.EditProfileResponse
|
||||||
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
|
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
|
||||||
import com.alya.ecommerce_serang.utils.FileUtils
|
import com.alya.ecommerce_serang.utils.FileUtils
|
||||||
@ -68,6 +70,16 @@ class UserRepository(private val apiService: ApiService) {
|
|||||||
return if (response.isSuccessful) response.body() else null
|
return if (response.isSuccessful) response.body() else null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun getListSubdistrict(cityId : String): SubdistrictResponse? {
|
||||||
|
val response = apiService.getSubdistrict(cityId)
|
||||||
|
return if (response.isSuccessful) response.body() else null
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getListVillages(subId: String): VillagesResponse? {
|
||||||
|
val response = apiService.getVillages(subId)
|
||||||
|
return if (response.isSuccessful) response.body() else null
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun registerUser(request: RegisterRequest): RegisterResponse {
|
suspend fun registerUser(request: RegisterRequest): RegisterResponse {
|
||||||
val response = apiService.register(request) // API call
|
val response = apiService.register(request) // API call
|
||||||
|
|
||||||
@ -87,7 +99,7 @@ class UserRepository(private val apiService: ApiService) {
|
|||||||
longitude: String,
|
longitude: String,
|
||||||
street: String,
|
street: String,
|
||||||
subdistrict: String,
|
subdistrict: String,
|
||||||
cityId: Int,
|
cityId: String,
|
||||||
provinceId: Int,
|
provinceId: Int,
|
||||||
postalCode: Int,
|
postalCode: Int,
|
||||||
detail: String,
|
detail: String,
|
||||||
|
@ -105,6 +105,7 @@ class LoginActivity : AppCompatActivity() {
|
|||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
is com.alya.ecommerce_serang.data.repository.Result.Error -> {
|
is com.alya.ecommerce_serang.data.repository.Result.Error -> {
|
||||||
|
Log.e("LoginActivity", "Login Failed: ${result.exception.message}")
|
||||||
Toast.makeText(this, "Login Failed: ${result.exception.message}", Toast.LENGTH_LONG).show()
|
Toast.makeText(this, "Login Failed: ${result.exception.message}", Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
is Result.Loading -> {
|
is Result.Loading -> {
|
||||||
|
@ -88,7 +88,7 @@ class RegisterStep2Fragment : Fragment() {
|
|||||||
|
|
||||||
// Update the email sent message
|
// Update the email sent message
|
||||||
userData?.let {
|
userData?.let {
|
||||||
binding.tvEmailSent.text = "We've sent a verification code to ${it.email}"
|
binding.tvEmailSent.text = "Kami telah mengirimkan kode OTP ke alamat email ${it.email}. Silahkan periksa email anda."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the resend cooldown timer
|
// Start the resend cooldown timer
|
||||||
@ -119,7 +119,7 @@ class RegisterStep2Fragment : Fragment() {
|
|||||||
Log.d(TAG, "verifyOtp called with OTP: $otp")
|
Log.d(TAG, "verifyOtp called with OTP: $otp")
|
||||||
|
|
||||||
if (otp.isEmpty()) {
|
if (otp.isEmpty()) {
|
||||||
Toast.makeText(requireContext(), "Please enter the verification code", Toast.LENGTH_SHORT).show()
|
Toast.makeText(requireContext(), "Masukkan kode OTP anda", Toast.LENGTH_SHORT).show()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,13 +153,13 @@ class RegisterStep2Fragment : Fragment() {
|
|||||||
}
|
}
|
||||||
is com.alya.ecommerce_serang.data.repository.Result.Success -> {
|
is com.alya.ecommerce_serang.data.repository.Result.Success -> {
|
||||||
binding.progressBar.visibility = View.GONE
|
binding.progressBar.visibility = View.GONE
|
||||||
Toast.makeText(requireContext(), "Verification code resent", Toast.LENGTH_SHORT).show()
|
Toast.makeText(requireContext(), "Kode OTP sudah dikirim", Toast.LENGTH_SHORT).show()
|
||||||
startResendCooldown()
|
startResendCooldown()
|
||||||
}
|
}
|
||||||
is Result.Error -> {
|
is Result.Error -> {
|
||||||
Log.e(TAG, "OTP request: Error - ${result.exception.message}")
|
Log.e(TAG, "OTP request: Error - ${result.exception.message}")
|
||||||
binding.progressBar.visibility = View.GONE
|
binding.progressBar.visibility = View.GONE
|
||||||
Toast.makeText(requireContext(), "Failed to resend code: ${result.exception.message}", Toast.LENGTH_SHORT).show()
|
Toast.makeText(requireContext(), "Gagal mengirim kode OTP", Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
Log.d(TAG, "OTP request: Unknown state")
|
Log.d(TAG, "OTP request: Unknown state")
|
||||||
@ -180,7 +180,7 @@ class RegisterStep2Fragment : Fragment() {
|
|||||||
countDownTimer = object : CountDownTimer(30000, 1000) {
|
countDownTimer = object : CountDownTimer(30000, 1000) {
|
||||||
override fun onTick(millisUntilFinished: Long) {
|
override fun onTick(millisUntilFinished: Long) {
|
||||||
timeRemaining = (millisUntilFinished / 1000).toInt()
|
timeRemaining = (millisUntilFinished / 1000).toInt()
|
||||||
binding.tvTimer.text = "Resend available in 00:${String.format("%02d", timeRemaining)}"
|
binding.tvTimer.text = "Kirim ulang OTP dalam waktu 00:${String.format("%02d", timeRemaining)}"
|
||||||
if (timeRemaining % 5 == 0) {
|
if (timeRemaining % 5 == 0) {
|
||||||
Log.d(TAG, "Cooldown remaining: $timeRemaining seconds")
|
Log.d(TAG, "Cooldown remaining: $timeRemaining seconds")
|
||||||
}
|
}
|
||||||
@ -188,7 +188,7 @@ class RegisterStep2Fragment : Fragment() {
|
|||||||
|
|
||||||
override fun onFinish() {
|
override fun onFinish() {
|
||||||
Log.d(TAG, "Cooldown finished, enabling resend button")
|
Log.d(TAG, "Cooldown finished, enabling resend button")
|
||||||
binding.tvTimer.text = "You can now resend the code"
|
binding.tvTimer.text = "Dapat mengirim ulang kode OTP"
|
||||||
binding.tvResendOtp.isEnabled = true
|
binding.tvResendOtp.isEnabled = true
|
||||||
binding.tvResendOtp.setTextColor(ContextCompat.getColor(requireContext(), R.color.blue1))
|
binding.tvResendOtp.setTextColor(ContextCompat.getColor(requireContext(), R.color.blue1))
|
||||||
timeRemaining = 0
|
timeRemaining = 0
|
||||||
@ -222,7 +222,8 @@ class RegisterStep2Fragment : Fragment() {
|
|||||||
binding.btnVerify.isEnabled = true
|
binding.btnVerify.isEnabled = true
|
||||||
|
|
||||||
// Show error message
|
// Show error message
|
||||||
Toast.makeText(requireContext(), "Registration Failed: ${result.exception.message}", Toast.LENGTH_SHORT).show()
|
Log.e(TAG, "Registration Failed: ${result.exception.message}")
|
||||||
|
Toast.makeText(requireContext(), "Gagal melakukan regsitrasi", Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
Log.d(TAG, "Registration: Unknown state")
|
Log.d(TAG, "Registration: Unknown state")
|
||||||
@ -269,7 +270,7 @@ class RegisterStep2Fragment : Fragment() {
|
|||||||
|
|
||||||
// Show error message but continue to Step 3 anyway
|
// Show error message but continue to Step 3 anyway
|
||||||
Log.e(TAG, "Login failed but proceeding to Step 3", result.exception)
|
Log.e(TAG, "Login failed but proceeding to Step 3", result.exception)
|
||||||
Toast.makeText(requireContext(), "Note: Auto-login failed, but registration was successful", Toast.LENGTH_SHORT).show()
|
Toast.makeText(requireContext(), "Gagal login, namun berhasil membuat akun", Toast.LENGTH_SHORT).show()
|
||||||
|
|
||||||
// Proceed to Step 3
|
// Proceed to Step 3
|
||||||
(activity as? RegisterActivity)?.navigateToStep(3, null)
|
(activity as? RegisterActivity)?.navigateToStep(3, null)
|
||||||
|
@ -23,7 +23,9 @@ import com.alya.ecommerce_serang.ui.auth.LoginActivity
|
|||||||
import com.alya.ecommerce_serang.ui.auth.RegisterActivity
|
import com.alya.ecommerce_serang.ui.auth.RegisterActivity
|
||||||
import com.alya.ecommerce_serang.ui.order.address.CityAdapter
|
import com.alya.ecommerce_serang.ui.order.address.CityAdapter
|
||||||
import com.alya.ecommerce_serang.ui.order.address.ProvinceAdapter
|
import com.alya.ecommerce_serang.ui.order.address.ProvinceAdapter
|
||||||
|
import com.alya.ecommerce_serang.ui.order.address.SubdsitrictAdapter
|
||||||
import com.alya.ecommerce_serang.ui.order.address.ViewState
|
import com.alya.ecommerce_serang.ui.order.address.ViewState
|
||||||
|
import com.alya.ecommerce_serang.ui.order.address.VillagesAdapter
|
||||||
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
||||||
import com.alya.ecommerce_serang.utils.SessionManager
|
import com.alya.ecommerce_serang.utils.SessionManager
|
||||||
import com.alya.ecommerce_serang.utils.viewmodel.RegisterViewModel
|
import com.alya.ecommerce_serang.utils.viewmodel.RegisterViewModel
|
||||||
@ -49,6 +51,8 @@ class RegisterStep3Fragment : Fragment() {
|
|||||||
// For province and city selection
|
// For province and city selection
|
||||||
private val provinceAdapter by lazy { ProvinceAdapter(requireContext()) }
|
private val provinceAdapter by lazy { ProvinceAdapter(requireContext()) }
|
||||||
private val cityAdapter by lazy { CityAdapter(requireContext()) }
|
private val cityAdapter by lazy { CityAdapter(requireContext()) }
|
||||||
|
private val subdistrictAdapter by lazy { SubdsitrictAdapter(requireContext()) }
|
||||||
|
private val villagesAdapter by lazy { VillagesAdapter(requireContext()) }
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "RegisterStep3Fragment"
|
private const val TAG = "RegisterStep3Fragment"
|
||||||
@ -114,7 +118,7 @@ class RegisterStep3Fragment : Fragment() {
|
|||||||
// Observe address submission state
|
// Observe address submission state
|
||||||
observeAddressSubmissionState()
|
observeAddressSubmissionState()
|
||||||
|
|
||||||
// Load provinces
|
// Load provinces from raja ongkir
|
||||||
Log.d(TAG, "Requesting provinces data")
|
Log.d(TAG, "Requesting provinces data")
|
||||||
registerViewModel.getProvinces()
|
registerViewModel.getProvinces()
|
||||||
setupProvinceObserver()
|
setupProvinceObserver()
|
||||||
@ -171,9 +175,10 @@ class RegisterStep3Fragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setupAutoComplete() {
|
private fun setupAutoComplete() {
|
||||||
// Same implementation as before
|
|
||||||
binding.autoCompleteProvinsi.setAdapter(provinceAdapter)
|
binding.autoCompleteProvinsi.setAdapter(provinceAdapter)
|
||||||
binding.autoCompleteKabupaten.setAdapter(cityAdapter)
|
binding.autoCompleteKabupaten.setAdapter(cityAdapter)
|
||||||
|
binding.autoCompleteKecamatan.setAdapter(subdistrictAdapter)
|
||||||
|
binding.autoCompleteDesa.setAdapter(villagesAdapter)
|
||||||
|
|
||||||
binding.autoCompleteProvinsi.setOnClickListener {
|
binding.autoCompleteProvinsi.setOnClickListener {
|
||||||
binding.autoCompleteProvinsi.showDropDown()
|
binding.autoCompleteProvinsi.showDropDown()
|
||||||
@ -188,6 +193,24 @@ class RegisterStep3Fragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.autoCompleteKecamatan.setOnClickListener {
|
||||||
|
if (subdistrictAdapter.count > 0) {
|
||||||
|
Log.d(TAG, "Subdistrict dropdown clicked, showing ${subdistrictAdapter.count} cities")
|
||||||
|
binding.autoCompleteKecamatan.showDropDown()
|
||||||
|
} else {
|
||||||
|
Toast.makeText(requireContext(), "Pilih kabupaten / kota terlebih dahulu", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.autoCompleteDesa.setOnClickListener {
|
||||||
|
if (villagesAdapter.count > 0) {
|
||||||
|
Log.d(TAG, "Village dropdown clicked, showing ${villagesAdapter.count} cities")
|
||||||
|
binding.autoCompleteDesa.showDropDown()
|
||||||
|
} else {
|
||||||
|
Toast.makeText(requireContext(), "Pilih kecamatan terlebih dahulu", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
binding.autoCompleteProvinsi.setOnItemClickListener { _, _, position, _ ->
|
binding.autoCompleteProvinsi.setOnItemClickListener { _, _, position, _ ->
|
||||||
val provinceId = provinceAdapter.getProvinceId(position)
|
val provinceId = provinceAdapter.getProvinceId(position)
|
||||||
Log.d(TAG, "Province selected at position $position, ID: $provinceId")
|
Log.d(TAG, "Province selected at position $position, ID: $provinceId")
|
||||||
@ -206,13 +229,44 @@ class RegisterStep3Fragment : Fragment() {
|
|||||||
|
|
||||||
cityId?.let { id ->
|
cityId?.let { id ->
|
||||||
Log.d(TAG, "Selected city ID set to: $id")
|
Log.d(TAG, "Selected city ID set to: $id")
|
||||||
registerViewModel.selectedCityId = id
|
registerViewModel.updateSelectedCityId(id)
|
||||||
|
registerViewModel.getSubdistrict(id)
|
||||||
|
binding.autoCompleteKecamatan.text.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.autoCompleteKecamatan.setOnItemClickListener{ _, _, position, _ ->
|
||||||
|
val subdistrictId = subdistrictAdapter.getSubdistrictId(position)
|
||||||
|
Log.d(TAG, "Subdistrict selected at position $position, ID: $subdistrictId")
|
||||||
|
|
||||||
|
subdistrictId?.let { id ->
|
||||||
|
Log.d(TAG, "Selected subdistrict ID set to: $id")
|
||||||
|
registerViewModel.selectedSubdistrict = id
|
||||||
|
registerViewModel.getVillages(id)
|
||||||
|
binding.autoCompleteDesa.text.clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.autoCompleteDesa.setOnItemClickListener{ _, _, position, _ ->
|
||||||
|
val villageId = villagesAdapter.getVillageId(position)
|
||||||
|
val postalCode = villagesAdapter.getPostalCode(position)
|
||||||
|
Log.d(TAG, "Village selected at position $position, ID: $villageId")
|
||||||
|
|
||||||
|
villageId?.let { id ->
|
||||||
|
Log.d(TAG, "Selected village ID set to: $id")
|
||||||
|
registerViewModel.selectedVillages = id
|
||||||
|
}
|
||||||
|
|
||||||
|
postalCode?.let { postCode ->
|
||||||
|
registerViewModel.selectedPostalCode = postCode
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.etKodePos.setText(registerViewModel.selectedPostalCode ?: "")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupProvinceObserver() {
|
private fun setupProvinceObserver() {
|
||||||
// Same implementation as before
|
// pake raja ongkir
|
||||||
registerViewModel.provincesState.observe(viewLifecycleOwner) { state ->
|
registerViewModel.provincesState.observe(viewLifecycleOwner) { state ->
|
||||||
when (state) {
|
when (state) {
|
||||||
is ViewState.Loading -> {
|
is ViewState.Loading -> {
|
||||||
@ -256,8 +310,46 @@ class RegisterStep3Fragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
registerViewModel.subdistrictState.observe(viewLifecycleOwner) { state ->
|
||||||
|
when (state) {
|
||||||
|
is ViewState.Loading -> {
|
||||||
|
binding.progressBarKecamatan.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
is ViewState.Success -> {
|
||||||
|
Log.d(TAG, "Subdistrict: Success - received ${state.data.size} kecamatan")
|
||||||
|
binding.progressBarKecamatan.visibility = View.GONE
|
||||||
|
subdistrictAdapter.updateData(state.data)
|
||||||
|
Log.d(TAG, "Updated subdistrict adapter with ${state.data.size} items")
|
||||||
|
}
|
||||||
|
is ViewState.Error -> {
|
||||||
|
Log.e(TAG, "Subdistrict: Error - ${state.message}")
|
||||||
|
binding.progressBarKecamatan.visibility = View.GONE
|
||||||
|
showError("Failed to load kecamatan: ${state.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
registerViewModel.villagesState.observe(viewLifecycleOwner) { state ->
|
||||||
|
when (state) {
|
||||||
|
is ViewState.Loading -> {
|
||||||
|
binding.progressBarDesa.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
is ViewState.Success -> {
|
||||||
|
Log.d(TAG, "Village: Success - received ${state.data.size} desa")
|
||||||
|
binding.progressBarDesa.visibility = View.GONE
|
||||||
|
villagesAdapter.updateData(state.data)
|
||||||
|
Log.d(TAG, "Updated village adapter with ${state.data.size} items")
|
||||||
|
}
|
||||||
|
is ViewState.Error -> {
|
||||||
|
Log.e(TAG, "Village: Error - ${state.message}")
|
||||||
|
binding.progressBarDesa.visibility = View.GONE
|
||||||
|
showError("Failed to load desa: ${state.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun submitAddress() {
|
private fun submitAddress() {
|
||||||
Log.d(TAG, "submitAddress called")
|
Log.d(TAG, "submitAddress called")
|
||||||
if (!validateAddressForm()) {
|
if (!validateAddressForm()) {
|
||||||
@ -276,13 +368,13 @@ class RegisterStep3Fragment : Fragment() {
|
|||||||
Log.d(TAG, "Using user ID: $userId")
|
Log.d(TAG, "Using user ID: $userId")
|
||||||
|
|
||||||
val street = binding.etDetailAlamat.text.toString().trim()
|
val street = binding.etDetailAlamat.text.toString().trim()
|
||||||
val subDistrict = binding.etKecamatan.text.toString().trim()
|
|
||||||
val postalCode = binding.etKodePos.text.toString().trim()
|
|
||||||
val recipient = binding.etNamaPenerima.text.toString().trim()
|
val recipient = binding.etNamaPenerima.text.toString().trim()
|
||||||
val phone = binding.etNomorHp.text.toString().trim()
|
val phone = binding.etNomorHp.text.toString().trim()
|
||||||
|
|
||||||
val provinceId = registerViewModel.selectedProvinceId?.toInt() ?: 0
|
val provinceId = registerViewModel.selectedProvinceId?.toInt() ?: 0
|
||||||
val cityId = registerViewModel.selectedCityId?.toInt() ?: 0
|
val cityId = registerViewModel.selectedCityId.toString()
|
||||||
|
val subDistrict = registerViewModel.selectedSubdistrict.toString()
|
||||||
|
val postalCode = registerViewModel.selectedPostalCode.toString()
|
||||||
|
|
||||||
Log.d(TAG, "Address data - Street: $street, SubDistrict: $subDistrict, PostalCode: $postalCode")
|
Log.d(TAG, "Address data - Street: $street, SubDistrict: $subDistrict, PostalCode: $postalCode")
|
||||||
Log.d(TAG, "Address data - Recipient: $recipient, Phone: $phone")
|
Log.d(TAG, "Address data - Recipient: $recipient, Phone: $phone")
|
||||||
@ -318,13 +410,13 @@ class RegisterStep3Fragment : Fragment() {
|
|||||||
|
|
||||||
private fun validateAddressForm(): Boolean {
|
private fun validateAddressForm(): Boolean {
|
||||||
val street = binding.etDetailAlamat.text.toString().trim()
|
val street = binding.etDetailAlamat.text.toString().trim()
|
||||||
val subDistrict = binding.etKecamatan.text.toString().trim()
|
|
||||||
val postalCode = binding.etKodePos.text.toString().trim()
|
|
||||||
val recipient = binding.etNamaPenerima.text.toString().trim()
|
val recipient = binding.etNamaPenerima.text.toString().trim()
|
||||||
val phone = binding.etNomorHp.text.toString().trim()
|
val phone = binding.etNomorHp.text.toString().trim()
|
||||||
|
|
||||||
val provinceId = registerViewModel.selectedProvinceId
|
val provinceId = registerViewModel.selectedProvinceId
|
||||||
val cityId = registerViewModel.selectedCityId
|
val cityId = registerViewModel.selectedCityId
|
||||||
|
val subDistrict = registerViewModel.selectedSubdistrict.toString()
|
||||||
|
val postalCode = registerViewModel.selectedPostalCode
|
||||||
|
|
||||||
Log.d(TAG, "Validating - Street: $street, SubDistrict: $subDistrict, PostalCode: $postalCode")
|
Log.d(TAG, "Validating - Street: $street, SubDistrict: $subDistrict, PostalCode: $postalCode")
|
||||||
Log.d(TAG, "Validating - Recipient: $recipient, Phone: $phone")
|
Log.d(TAG, "Validating - Recipient: $recipient, Phone: $phone")
|
||||||
@ -409,8 +501,4 @@ class RegisterStep3Fragment : Fragment() {
|
|||||||
ViewCompat.setWindowInsetsAnimationCallback(binding.root, null)
|
ViewCompat.setWindowInsetsAnimationCallback(binding.root, null)
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// // Data classes for province and city
|
|
||||||
// data class Province(val id: String, val name: String)
|
|
||||||
// data class City(val id: String, val name: String)
|
|
||||||
}
|
}
|
@ -2,6 +2,7 @@ package com.alya.ecommerce_serang.ui.home
|
|||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
@ -65,6 +66,16 @@ class SearchResultsAdapter(
|
|||||||
|
|
||||||
val storeName = product.storeId?.let { storeMap[it]?.storeName } ?: "Unknown Store"
|
val storeName = product.storeId?.let { storeMap[it]?.storeName } ?: "Unknown Store"
|
||||||
binding.tvStoreName.text = storeName
|
binding.tvStoreName.text = storeName
|
||||||
|
val ratingStr = product.rating
|
||||||
|
val ratingValue = ratingStr?.toFloatOrNull()
|
||||||
|
|
||||||
|
if (ratingValue != null && ratingValue > 0f) {
|
||||||
|
binding.rating.text = String.format("%.1f", ratingValue)
|
||||||
|
binding.rating.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
binding.rating.text = "Belum ada rating"
|
||||||
|
binding.rating.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ class CheckoutViewModel(private val repository: OrderRepository) : ViewModel() {
|
|||||||
shipPrice = 0, // Will be set when user selects shipping
|
shipPrice = 0, // Will be set when user selects shipping
|
||||||
shipName = "",
|
shipName = "",
|
||||||
shipService = "",
|
shipService = "",
|
||||||
isNego = false, // Default value
|
isNego = false, // Default value
|
||||||
productId = productId,
|
productId = productId,
|
||||||
quantity = quantity,
|
quantity = quantity,
|
||||||
shipEtd = "",
|
shipEtd = "",
|
||||||
|
@ -289,7 +289,7 @@ class AddAddressActivity : AppCompatActivity() {
|
|||||||
val isStoreLocation = false
|
val isStoreLocation = false
|
||||||
|
|
||||||
val provinceId = viewModel.selectedProvinceId
|
val provinceId = viewModel.selectedProvinceId
|
||||||
val cityId = viewModel.selectedCityId
|
val cityId = viewModel.selectedCityId.toString()
|
||||||
|
|
||||||
Log.d(TAG, "Form data: street=$street, subDistrict=$subDistrict, postalCode=$postalCode, " +
|
Log.d(TAG, "Form data: street=$street, subDistrict=$subDistrict, postalCode=$postalCode, " +
|
||||||
"recipient=$recipient, phone=$phone, userId=$userId, provinceId=$provinceId, cityId=$cityId, " +
|
"recipient=$recipient, phone=$phone, userId=$userId, provinceId=$provinceId, cityId=$cityId, " +
|
||||||
|
@ -36,8 +36,8 @@ class AddAddressViewModel(private val repository: OrderRepository, private val u
|
|||||||
get() = savedStateHandle.get<Int>("selectedProvinceId")
|
get() = savedStateHandle.get<Int>("selectedProvinceId")
|
||||||
set(value) { savedStateHandle["selectedProvinceId"] = value }
|
set(value) { savedStateHandle["selectedProvinceId"] = value }
|
||||||
|
|
||||||
var selectedCityId: Int?
|
var selectedCityId: String?
|
||||||
get() = savedStateHandle.get<Int>("selectedCityId")
|
get() = savedStateHandle.get<String>("selectedCityId")
|
||||||
set(value) { savedStateHandle["selectedCityId"] = value }
|
set(value) { savedStateHandle["selectedCityId"] = value }
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -129,7 +129,7 @@ class AddAddressViewModel(private val repository: OrderRepository, private val u
|
|||||||
selectedProvinceId = id
|
selectedProvinceId = id
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setSelectedCityId(id: Int) {
|
fun updateSelectedCityId(id: String) {
|
||||||
selectedCityId = id
|
selectedCityId = id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@ import android.util.Log
|
|||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
import com.alya.ecommerce_serang.data.api.response.customer.order.CitiesItem
|
import com.alya.ecommerce_serang.data.api.response.customer.order.CitiesItem
|
||||||
import com.alya.ecommerce_serang.data.api.response.customer.order.ProvincesItem
|
import com.alya.ecommerce_serang.data.api.response.customer.order.ProvincesItem
|
||||||
|
import com.alya.ecommerce_serang.data.api.response.customer.order.SubdistrictsItem
|
||||||
|
import com.alya.ecommerce_serang.data.api.response.customer.order.VillagesItem
|
||||||
|
|
||||||
// UI adapters and helpers
|
// UI adapters and helpers
|
||||||
class ProvinceAdapter(
|
class ProvinceAdapter(
|
||||||
@ -12,6 +14,86 @@ class ProvinceAdapter(
|
|||||||
resource: Int = android.R.layout.simple_dropdown_item_1line
|
resource: Int = android.R.layout.simple_dropdown_item_1line
|
||||||
) : ArrayAdapter<String>(context, resource, ArrayList()) {
|
) : ArrayAdapter<String>(context, resource, ArrayList()) {
|
||||||
|
|
||||||
|
// companion object {
|
||||||
|
// private const val TAG = "ProvinceAdapter"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // --- Static list of provinces ---------------------------------------------------------------
|
||||||
|
// private val provinces = listOf(
|
||||||
|
// ProvincesItem(1, "Aceh"),
|
||||||
|
// ProvincesItem(2, "Sumatera Utara"),
|
||||||
|
// ProvincesItem(3, "Sumatera Barat"),
|
||||||
|
// ProvincesItem(4, "Riau"),
|
||||||
|
// ProvincesItem(5, "Kepulauan Riau"),
|
||||||
|
// ProvincesItem(6, "Jambi"),
|
||||||
|
// ProvincesItem(7, "Sumatera Selatan"),
|
||||||
|
// ProvincesItem(8, "Kepulauan Bangka Belitung"),
|
||||||
|
// ProvincesItem(9, "Bengkulu"),
|
||||||
|
// ProvincesItem(10, "Lampung"),
|
||||||
|
// ProvincesItem(11, "DKI Jakarta"),
|
||||||
|
// ProvincesItem(12, "Jawa Barat"),
|
||||||
|
// ProvincesItem(13, "Banten"),
|
||||||
|
// ProvincesItem(14, "Jawa Tengah"),
|
||||||
|
// ProvincesItem(15, "Daerah Istimewa Yogyakarta"),
|
||||||
|
// ProvincesItem(16, "Jawa Timur"),
|
||||||
|
// ProvincesItem(17, "Bali"),
|
||||||
|
// ProvincesItem(18, "Nusa Tenggara Barat"),
|
||||||
|
// ProvincesItem(19, "Nusa Tenggara Timur"),
|
||||||
|
// ProvincesItem(20, "Kalimantan Barat"),
|
||||||
|
// ProvincesItem(21, "Kalimantan Tengah"),
|
||||||
|
// ProvincesItem(22, "Kalimantan Selatan"),
|
||||||
|
// ProvincesItem(23, "Kalimantan Timur"),
|
||||||
|
// ProvincesItem(24, "Kalimantan Utara"),
|
||||||
|
// ProvincesItem(25, "Sulawesi Utara"),
|
||||||
|
// ProvincesItem(26, "Gorontalo"),
|
||||||
|
// ProvincesItem(27, "Sulawesi Tengah"),
|
||||||
|
// ProvincesItem(28, "Sulawesi Barat"),
|
||||||
|
// ProvincesItem(29, "Sulawesi Selatan"),
|
||||||
|
// ProvincesItem(30, "Sulawesi Tenggara"),
|
||||||
|
// ProvincesItem(31, "Maluku"),
|
||||||
|
// ProvincesItem(32, "Maluku Utara"),
|
||||||
|
// ProvincesItem(33, "Papua Barat"),
|
||||||
|
// ProvincesItem(34, "Papua"),
|
||||||
|
// ProvincesItem(35, "Papua Tengah"),
|
||||||
|
// ProvincesItem(36, "Papua Pegunungan"),
|
||||||
|
// ProvincesItem(37, "Papua Selatan"),
|
||||||
|
// ProvincesItem(38, "Papua Barat Daya")
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// // --- Init block -----------------------------------------------------------------------------
|
||||||
|
// init {
|
||||||
|
// addAll(getProvinceNames()) // pre‑populate adapter
|
||||||
|
// Log.d(TAG, "Adapter created with ${count} provinces")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // --- Public helper functions ----------------------------------------------------------------
|
||||||
|
// fun updateData(newProvinces: List<ProvincesItem>) {
|
||||||
|
// // If you actually want to replace the list, comment this line
|
||||||
|
// // provinces = newProvinces // (make `provinces` var instead of val)
|
||||||
|
//
|
||||||
|
// clear()
|
||||||
|
// addAll(newProvinces.map { it.province })
|
||||||
|
// notifyDataSetChanged()
|
||||||
|
//
|
||||||
|
// Log.d(TAG, "updateData(): updated with ${newProvinces.size} provinces")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun getProvinceId(position: Int): Int? {
|
||||||
|
// val id = provinces.getOrNull(position)?.provinceId
|
||||||
|
// Log.d(TAG, "getProvinceId(): position=$position, id=$id")
|
||||||
|
// return id
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun getProvinceItem(position: Int): ProvincesItem? {
|
||||||
|
// val item = provinces.getOrNull(position)
|
||||||
|
// Log.d(TAG, "getProvinceItem(): position=$position, item=$item")
|
||||||
|
// return item
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // --- Private helpers ------------------------------------------------------------------------
|
||||||
|
// private fun getProvinceNames(): List<String> = provinces.map { it.province }
|
||||||
|
|
||||||
|
//call from endpoint
|
||||||
private val provinces = ArrayList<ProvincesItem>()
|
private val provinces = ArrayList<ProvincesItem>()
|
||||||
|
|
||||||
fun updateData(newProvinces: List<ProvincesItem>) {
|
fun updateData(newProvinces: List<ProvincesItem>) {
|
||||||
@ -46,7 +128,52 @@ class CityAdapter(
|
|||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCityId(position: Int): Int? {
|
fun getCityId(position: Int): String? {
|
||||||
return cities.getOrNull(position)?.cityId?.toIntOrNull()
|
return cities.getOrNull(position)?.cityId?.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SubdsitrictAdapter(
|
||||||
|
context: Context,
|
||||||
|
resource: Int = android.R.layout.simple_dropdown_item_1line
|
||||||
|
) : ArrayAdapter<String>(context, resource, ArrayList()) {
|
||||||
|
|
||||||
|
private val cities = ArrayList<SubdistrictsItem>()
|
||||||
|
|
||||||
|
fun updateData(newCities: List<SubdistrictsItem>) {
|
||||||
|
cities.clear()
|
||||||
|
cities.addAll(newCities)
|
||||||
|
|
||||||
|
clear()
|
||||||
|
addAll(cities.map { it.subdistrictName })
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSubdistrictId(position: Int): String? {
|
||||||
|
return cities.getOrNull(position)?.subdistrictId?.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class VillagesAdapter(
|
||||||
|
context: Context,
|
||||||
|
resource: Int = android.R.layout.simple_dropdown_item_1line
|
||||||
|
) : ArrayAdapter<String>(context, resource, ArrayList()) {
|
||||||
|
|
||||||
|
private val villages = ArrayList<VillagesItem>()
|
||||||
|
|
||||||
|
fun updateData(newCities: List<VillagesItem>) {
|
||||||
|
villages.clear()
|
||||||
|
villages.addAll(newCities)
|
||||||
|
|
||||||
|
clear()
|
||||||
|
addAll(villages.map { it.villageName })
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getVillageId(position: Int): String? {
|
||||||
|
return villages.getOrNull(position)?.villageId?.toString()
|
||||||
|
}
|
||||||
|
fun getPostalCode(position: Int): String?{
|
||||||
|
return villages.getOrNull(position)?.postalCode
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -39,7 +39,6 @@ import okhttp3.MultipartBody
|
|||||||
import okhttp3.RequestBody.Companion.asRequestBody
|
import okhttp3.RequestBody.Companion.asRequestBody
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.text.NumberFormat
|
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
@ -63,7 +62,6 @@ class AddEvidencePaymentActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private val paymentMethods = arrayOf(
|
private val paymentMethods = arrayOf(
|
||||||
"Transfer Bank",
|
"Transfer Bank",
|
||||||
"E-Wallet",
|
|
||||||
"QRIS",
|
"QRIS",
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -129,7 +127,7 @@ class AddEvidencePaymentActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setupUI() {
|
private fun setupUI() {
|
||||||
val paymentMethods = listOf("Transfer Bank", "COD", "QRIS")
|
val paymentMethods = listOf("Transfer Bank", "QRIS")
|
||||||
val adapter = SpinnerCardAdapter(this, paymentMethods)
|
val adapter = SpinnerCardAdapter(this, paymentMethods)
|
||||||
binding.spinnerPaymentMethod.adapter = adapter
|
binding.spinnerPaymentMethod.adapter = adapter
|
||||||
}
|
}
|
||||||
@ -320,11 +318,12 @@ class AddEvidencePaymentActivity : AppCompatActivity() {
|
|||||||
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
|
||||||
|
|
||||||
if (binding.etAccountNumber.text.toString().trim().isEmpty()) {
|
// if (binding.etAccountNumber.text.toString().trim().isEmpty()) {
|
||||||
Toast.makeText(this, "Silahkan isi nomor rekening/HP", Toast.LENGTH_SHORT).show()
|
// Toast.makeText(this, "Silahkan isi nomor rekening/HP", Toast.LENGTH_SHORT).show()
|
||||||
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()
|
||||||
|
@ -213,14 +213,15 @@ class OrderHistoryAdapter(
|
|||||||
visibility = View.VISIBLE
|
visibility = View.VISIBLE
|
||||||
text = itemView.context.getString(R.string.dl_processed)
|
text = itemView.context.getString(R.string.dl_processed)
|
||||||
}
|
}
|
||||||
btnLeft.apply {
|
// gabisa complaint
|
||||||
visibility = View.VISIBLE
|
// btnLeft.apply {
|
||||||
text = itemView.context.getString(R.string.canceled_order_btn)
|
// visibility = View.VISIBLE
|
||||||
setOnClickListener {
|
// text = itemView.context.getString(R.string.canceled_order_btn)
|
||||||
showCancelOrderDialog(order.orderId.toString())
|
// setOnClickListener {
|
||||||
viewModel.refreshOrders()
|
// showCancelOrderDialog(order.orderId.toString())
|
||||||
}
|
// viewModel.refreshOrders()
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
"shipped" -> {
|
"shipped" -> {
|
||||||
// Untuk status shipped, tampilkan "Lacak Pengiriman" dan "Terima Barang"
|
// Untuk status shipped, tampilkan "Lacak Pengiriman" dan "Terima Barang"
|
||||||
@ -268,13 +269,21 @@ class OrderHistoryAdapter(
|
|||||||
text = itemView.context.getString(R.string.dl_shipped)
|
text = itemView.context.getString(R.string.dl_shipped)
|
||||||
}
|
}
|
||||||
btnRight.apply {
|
btnRight.apply {
|
||||||
visibility = View.VISIBLE
|
val checkReview = order.orderItems[0].reviewId
|
||||||
text = itemView.context.getString(R.string.add_review)
|
if (checkReview > 0){
|
||||||
setOnClickListener {
|
visibility = View.VISIBLE
|
||||||
addReviewProduct(order)
|
text = itemView.context.getString(R.string.add_review)
|
||||||
viewModel.refreshOrders()
|
setOnClickListener {
|
||||||
// Handle click event
|
|
||||||
|
addReviewProduct(order)
|
||||||
|
// viewModel.refreshOrders()
|
||||||
|
// Handle click event
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
deadlineDate.apply {
|
deadlineDate.apply {
|
||||||
visibility = View.VISIBLE
|
visibility = View.VISIBLE
|
||||||
@ -518,7 +527,7 @@ class OrderHistoryAdapter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create and show the bottom sheet using the obtained FragmentManager
|
// cancel sebelum bayar
|
||||||
val bottomSheet = CancelOrderBottomSheet(
|
val bottomSheet = CancelOrderBottomSheet(
|
||||||
orderId = orderId,
|
orderId = orderId,
|
||||||
onOrderCancelled = {
|
onOrderCancelled = {
|
||||||
@ -531,6 +540,7 @@ class OrderHistoryAdapter(
|
|||||||
bottomSheet.show(fragmentActivity.supportFragmentManager, CancelOrderBottomSheet.TAG)
|
bottomSheet.show(fragmentActivity.supportFragmentManager, CancelOrderBottomSheet.TAG)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tambah review / ulasan
|
||||||
private fun addReviewProduct(order: OrdersItem) {
|
private fun addReviewProduct(order: OrdersItem) {
|
||||||
// Use ViewModel to fetch order details
|
// Use ViewModel to fetch order details
|
||||||
viewModel.getOrderDetails(order.orderId)
|
viewModel.getOrderDetails(order.orderId)
|
||||||
@ -550,7 +560,7 @@ class OrderHistoryAdapter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Observe the order details result
|
// Observe order items
|
||||||
viewModel.orderItems.observe(itemView.findViewTreeLifecycleOwner()!!) { orderItems ->
|
viewModel.orderItems.observe(itemView.findViewTreeLifecycleOwner()!!) { orderItems ->
|
||||||
if (orderItems != null && orderItems.isNotEmpty()) {
|
if (orderItems != null && orderItems.isNotEmpty()) {
|
||||||
// For single item review
|
// For single item review
|
||||||
|
@ -55,7 +55,7 @@ class CancelOrderBottomSheet(
|
|||||||
val btnConfirm = view.findViewById<Button>(R.id.btn_confirm)
|
val btnConfirm = view.findViewById<Button>(R.id.btn_confirm)
|
||||||
|
|
||||||
// Set the title
|
// Set the title
|
||||||
tvTitle.text = "Cancel Order #$orderId"
|
tvTitle.text = "Batalkan Pesanan #$orderId"
|
||||||
|
|
||||||
// Set up the spinner with cancellation reasons
|
// Set up the spinner with cancellation reasons
|
||||||
setupReasonSpinner(spinnerReason)
|
setupReasonSpinner(spinnerReason)
|
||||||
@ -94,11 +94,11 @@ class CancelOrderBottomSheet(
|
|||||||
private fun getCancellationReasons(): List<CancelOrderReq> {
|
private fun getCancellationReasons(): List<CancelOrderReq> {
|
||||||
// These should ideally come from the server or a configuration
|
// These should ideally come from the server or a configuration
|
||||||
return listOf(
|
return listOf(
|
||||||
CancelOrderReq(1, "Changed my mind"),
|
CancelOrderReq(1, "Berubah pikiran"),
|
||||||
CancelOrderReq(2, "Found a better option"),
|
CancelOrderReq(2, "Menemukan pilihan yang lebih baik"),
|
||||||
CancelOrderReq(3, "Ordered by mistake"),
|
CancelOrderReq(3, "Kesalahan pemesanan"),
|
||||||
CancelOrderReq(4, "Delivery time too long"),
|
CancelOrderReq(4, "Waktu pengiriman lama"),
|
||||||
CancelOrderReq(5, "Other reason")
|
CancelOrderReq(5, "Lainnya")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,18 +289,18 @@ class DetailOrderStatusActivity : AppCompatActivity() {
|
|||||||
binding.tvStatusNote.visibility = View.VISIBLE
|
binding.tvStatusNote.visibility = View.VISIBLE
|
||||||
binding.tvStatusNote.text = "Menunggu pesanan dikonfirmasi penjual ${formatDatePay(orders.updatedAt)}"
|
binding.tvStatusNote.text = "Menunggu pesanan dikonfirmasi penjual ${formatDatePay(orders.updatedAt)}"
|
||||||
binding.tvPaymentDeadlineLabel.text = "Batas konfirmasi penjual:"
|
binding.tvPaymentDeadlineLabel.text = "Batas konfirmasi penjual:"
|
||||||
binding.tvPaymentDeadline.text = formatDatePay(orders.updatedAt)
|
binding.tvPaymentDeadline.text = formatDatePaid(orders.updatedAt)
|
||||||
|
|
||||||
// Set buttons
|
// cancel pesanan
|
||||||
binding.btnSecondary.apply {
|
// binding.btnSecondary.apply {
|
||||||
visibility = View.VISIBLE
|
// visibility = View.VISIBLE
|
||||||
text = "Batalkan Pesanan"
|
// text = "Batalkan Pesanan"
|
||||||
setOnClickListener {
|
// setOnClickListener {
|
||||||
Log.d(TAG, "Cancel Order button clicked")
|
// Log.d(TAG, "Cancel Order button clicked")
|
||||||
showCancelOrderDialog(orders.orderId.toString())
|
// showCancelOrderDialog(orders.orderId.toString())
|
||||||
viewModel.getOrderDetails(orders.orderId)
|
// viewModel.getOrderDetails(orders.orderId)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
"processed" -> {
|
"processed" -> {
|
||||||
Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for processed order")
|
Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for processed order")
|
||||||
@ -309,7 +309,7 @@ class DetailOrderStatusActivity : AppCompatActivity() {
|
|||||||
binding.tvStatusNote.visibility = View.VISIBLE
|
binding.tvStatusNote.visibility = View.VISIBLE
|
||||||
binding.tvStatusNote.text = "Penjual sedang memproses pesanan Anda"
|
binding.tvStatusNote.text = "Penjual sedang memproses pesanan Anda"
|
||||||
binding.tvPaymentDeadlineLabel.text = "Batas diproses penjual:"
|
binding.tvPaymentDeadlineLabel.text = "Batas diproses penjual:"
|
||||||
binding.tvPaymentDeadline.text = formatDatePay(orders.updatedAt)
|
binding.tvPaymentDeadline.text = formatDateProcessed(orders.updatedAt)
|
||||||
|
|
||||||
binding.btnSecondary.apply {
|
binding.btnSecondary.apply {
|
||||||
visibility = View.VISIBLE
|
visibility = View.VISIBLE
|
||||||
@ -333,7 +333,7 @@ class DetailOrderStatusActivity : AppCompatActivity() {
|
|||||||
binding.tvStatusNote.visibility = View.VISIBLE
|
binding.tvStatusNote.visibility = View.VISIBLE
|
||||||
binding.tvStatusNote.text = "Pesanan Anda sedang dalam perjalanan. Akan sampai sekitar ${formatShipmentDate(orders.updatedAt, orders.etd ?: "0")}"
|
binding.tvStatusNote.text = "Pesanan Anda sedang dalam perjalanan. Akan sampai sekitar ${formatShipmentDate(orders.updatedAt, orders.etd ?: "0")}"
|
||||||
binding.tvPaymentDeadlineLabel.text = "Estimasi pesanan sampai:"
|
binding.tvPaymentDeadlineLabel.text = "Estimasi pesanan sampai:"
|
||||||
binding.tvPaymentDeadline.text = formatShipmentDate(orders.updatedAt, orders.etd ?: "0")
|
binding.tvPaymentDeadline.text = formatShipmentDate(orders.autoCompletedAt, orders.etd ?: "0")
|
||||||
|
|
||||||
binding.btnSecondary.apply {
|
binding.btnSecondary.apply {
|
||||||
visibility = View.VISIBLE
|
visibility = View.VISIBLE
|
||||||
@ -367,7 +367,7 @@ class DetailOrderStatusActivity : AppCompatActivity() {
|
|||||||
binding.tvStatusHeader.text = "Pesanan Selesai"
|
binding.tvStatusHeader.text = "Pesanan Selesai"
|
||||||
binding.tvStatusNote.visibility = View.GONE
|
binding.tvStatusNote.visibility = View.GONE
|
||||||
binding.tvPaymentDeadlineLabel.text = "Pesanan selesai:"
|
binding.tvPaymentDeadlineLabel.text = "Pesanan selesai:"
|
||||||
binding.tvPaymentDeadline.text = formatDate(orders.autoCompletedAt.toString())
|
binding.tvPaymentDeadline.text = formatDate(orders.updatedAt.toString())
|
||||||
|
|
||||||
binding.btnPrimary.apply {
|
binding.btnPrimary.apply {
|
||||||
visibility = View.VISIBLE
|
visibility = View.VISIBLE
|
||||||
@ -386,7 +386,7 @@ class DetailOrderStatusActivity : AppCompatActivity() {
|
|||||||
"canceled" -> {
|
"canceled" -> {
|
||||||
Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for canceled order")
|
Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for canceled order")
|
||||||
|
|
||||||
binding.tvStatusHeader.text = "Pesanan Selesai"
|
binding.tvStatusHeader.text = "Pesanan Dibatalkan"
|
||||||
binding.tvStatusNote.visibility = View.VISIBLE
|
binding.tvStatusNote.visibility = View.VISIBLE
|
||||||
binding.tvStatusNote.text = "Pesanan dibatalkan: ${orders.cancelReason ?: "Alasan tidak diberikan"}"
|
binding.tvStatusNote.text = "Pesanan dibatalkan: ${orders.cancelReason ?: "Alasan tidak diberikan"}"
|
||||||
binding.tvPaymentDeadlineLabel.text = "Tanggal dibatalkan: "
|
binding.tvPaymentDeadlineLabel.text = "Tanggal dibatalkan: "
|
||||||
@ -598,10 +598,6 @@ class DetailOrderStatusActivity : AppCompatActivity() {
|
|||||||
val bottomSheet = CancelOrderBottomSheet(
|
val bottomSheet = CancelOrderBottomSheet(
|
||||||
orderId = orderId,
|
orderId = orderId,
|
||||||
onOrderCancelled = {
|
onOrderCancelled = {
|
||||||
// Handle the successful cancellation
|
|
||||||
// Refresh the data
|
|
||||||
|
|
||||||
// Show a success message
|
|
||||||
Toast.makeText(this, "Order cancelled successfully", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, "Order cancelled successfully", Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -673,6 +669,73 @@ class DetailOrderStatusActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun formatDatePaid(dateString: String): String {
|
||||||
|
Log.d(TAG, "formatDatePay: Formatting payment date: $dateString")
|
||||||
|
|
||||||
|
return try {
|
||||||
|
// Parse the ISO 8601 date
|
||||||
|
val isoDateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault())
|
||||||
|
isoDateFormat.timeZone = TimeZone.getTimeZone("UTC")
|
||||||
|
|
||||||
|
val createdDate = isoDateFormat.parse(dateString)
|
||||||
|
|
||||||
|
// Add 24 hours to get due date
|
||||||
|
val calendar = Calendar.getInstance()
|
||||||
|
calendar.time = createdDate
|
||||||
|
calendar.add(Calendar.HOUR, 120)
|
||||||
|
val dueDate = calendar.time
|
||||||
|
|
||||||
|
val timeFormat = SimpleDateFormat("HH:mm", Locale("id", "ID"))
|
||||||
|
val dateFormat = SimpleDateFormat("dd MMM yyyy", Locale("id", "ID"))
|
||||||
|
|
||||||
|
val timePart = timeFormat.format(dueDate)
|
||||||
|
val datePart = dateFormat.format(dueDate)
|
||||||
|
|
||||||
|
val formatted = "$timePart\n$datePart"
|
||||||
|
|
||||||
|
Log.d(TAG, "formatDatePay: Formatted payment date: $formatted")
|
||||||
|
formatted
|
||||||
|
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "formatDatePay: Error formatting date: ${e.message}", e)
|
||||||
|
dateString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//format batas tgl diproses
|
||||||
|
private fun formatDateProcessed(dateString: String): String {
|
||||||
|
Log.d(TAG, "formatDatePay: Formatting payment date: $dateString")
|
||||||
|
|
||||||
|
return try {
|
||||||
|
// Parse the ISO 8601 date
|
||||||
|
val isoDateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault())
|
||||||
|
isoDateFormat.timeZone = TimeZone.getTimeZone("UTC")
|
||||||
|
|
||||||
|
val createdDate = isoDateFormat.parse(dateString)
|
||||||
|
|
||||||
|
// Add 24 hours to get due date
|
||||||
|
val calendar = Calendar.getInstance()
|
||||||
|
calendar.time = createdDate
|
||||||
|
calendar.add(Calendar.HOUR, 72)
|
||||||
|
val dueDate = calendar.time
|
||||||
|
|
||||||
|
val timeFormat = SimpleDateFormat("HH:mm", Locale("id", "ID"))
|
||||||
|
val dateFormat = SimpleDateFormat("dd MMM yyyy", Locale("id", "ID"))
|
||||||
|
|
||||||
|
val timePart = timeFormat.format(dueDate)
|
||||||
|
val datePart = dateFormat.format(dueDate)
|
||||||
|
|
||||||
|
val formatted = "$timePart\n$datePart"
|
||||||
|
|
||||||
|
Log.d(TAG, "formatDatePay: Formatted payment date: $formatted")
|
||||||
|
formatted
|
||||||
|
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "formatDatePay: Error formatting date: ${e.message}", e)
|
||||||
|
dateString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun formatShipmentDate(dateString: String, estimateString: String): String {
|
private fun formatShipmentDate(dateString: String, estimateString: String): String {
|
||||||
Log.d(TAG, "formatShipmentDate: Formatting shipment date: $dateString with ETD: $estimateString")
|
Log.d(TAG, "formatShipmentDate: Formatting shipment date: $dateString with ETD: $estimateString")
|
||||||
|
|
||||||
@ -696,7 +759,6 @@ class DetailOrderStatusActivity : AppCompatActivity() {
|
|||||||
calendar.time = it
|
calendar.time = it
|
||||||
|
|
||||||
// Add estimated days
|
// Add estimated days
|
||||||
calendar.add(Calendar.DAY_OF_MONTH, estimate)
|
|
||||||
val formatted = outputFormat.format(calendar.time)
|
val formatted = outputFormat.format(calendar.time)
|
||||||
|
|
||||||
Log.d(TAG, "formatShipmentDate: Estimated arrival date: $formatted")
|
Log.d(TAG, "formatShipmentDate: Estimated arrival date: $formatted")
|
||||||
|
@ -75,6 +75,7 @@ class DetailOrderViewModel(private val orderRepository: OrderRepository): ViewMo
|
|||||||
orderRepository.submitComplaint(orderId.toString(), reason, imageFile)
|
orderRepository.submitComplaint(orderId.toString(), reason, imageFile)
|
||||||
_isSuccess.value = true
|
_isSuccess.value = true
|
||||||
_message.value = "Order canceled successfully"
|
_message.value = "Order canceled successfully"
|
||||||
|
Log.d("DetailOrderViewModel", "Complaint order success")
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
_isSuccess.value = false
|
_isSuccess.value = false
|
||||||
|
@ -164,6 +164,7 @@ class DetailProductActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//info toko
|
||||||
private fun updateStoreInfo(store: StoreItem?) {
|
private fun updateStoreInfo(store: StoreItem?) {
|
||||||
store?.let {
|
store?.let {
|
||||||
binding.tvSellerName.text = it.storeName
|
binding.tvSellerName.text = it.storeName
|
||||||
@ -230,9 +231,8 @@ class DetailProductActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private fun updateUI(product: Product){
|
private fun updateUI(product: Product){
|
||||||
binding.tvProductName.text = product.productName
|
binding.tvProductName.text = product.productName
|
||||||
binding.tvPrice.text = "Rp${formatCurrency(product.price.toDouble())}"
|
binding.tvPrice.text = formatCurrency(product.price.toDouble())
|
||||||
binding.tvSold.text = "Terjual ${product.totalSold} buah"
|
binding.tvSold.text = "Terjual ${product.totalSold} buah"
|
||||||
binding.tvRating.text = product.rating
|
|
||||||
binding.tvWeight.text = "${product.weight} gram"
|
binding.tvWeight.text = "${product.weight} gram"
|
||||||
binding.tvStock.text = "${product.stock} buah"
|
binding.tvStock.text = "${product.stock} buah"
|
||||||
binding.tvCategory.text = product.productCategory
|
binding.tvCategory.text = product.productCategory
|
||||||
@ -243,7 +243,7 @@ class DetailProductActivity : AppCompatActivity() {
|
|||||||
isWholesaleSelected = false // Default to regular pricing
|
isWholesaleSelected = false // Default to regular pricing
|
||||||
if (isWholesaleAvailable) {
|
if (isWholesaleAvailable) {
|
||||||
binding.containerWholesale.visibility = View.VISIBLE
|
binding.containerWholesale.visibility = View.VISIBLE
|
||||||
binding.tvPriceWholesale.text = "Rp${formatCurrency(product.wholesalePrice!!.toDouble())}"
|
binding.tvPriceWholesale.text = formatCurrency(product.wholesalePrice!!.toDouble())
|
||||||
binding.descMinOrder.text = "Minimal pembelian ${minOrder}"
|
binding.descMinOrder.text = "Minimal pembelian ${minOrder}"
|
||||||
} else {
|
} else {
|
||||||
binding.containerWholesale.visibility = View.GONE
|
binding.containerWholesale.visibility = View.GONE
|
||||||
@ -281,6 +281,17 @@ class DetailProductActivity : AppCompatActivity() {
|
|||||||
.load(fullImageUrl)
|
.load(fullImageUrl)
|
||||||
.placeholder(R.drawable.placeholder_image)
|
.placeholder(R.drawable.placeholder_image)
|
||||||
.into(binding.ivProductImage)
|
.into(binding.ivProductImage)
|
||||||
|
|
||||||
|
val ratingStr = product.rating
|
||||||
|
val ratingValue = ratingStr?.toFloatOrNull()
|
||||||
|
|
||||||
|
if (ratingValue != null && ratingValue > 0f) {
|
||||||
|
binding.tvRating.text = String.format("%.1f", ratingValue)
|
||||||
|
binding.tvRating.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
binding.tvRating.text = "Belum ada rating"
|
||||||
|
binding.tvRating.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleAllReviewsClick(productId: Int) {
|
private fun handleAllReviewsClick(productId: Int) {
|
||||||
@ -347,6 +358,7 @@ class DetailProductActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//dialog tambah quantity dan harga grosir
|
||||||
private fun showQuantityDialog(productId: Int, isBuyNow: Boolean) {
|
private fun showQuantityDialog(productId: Int, isBuyNow: Boolean) {
|
||||||
val bottomSheetDialog = BottomSheetDialog(this)
|
val bottomSheetDialog = BottomSheetDialog(this)
|
||||||
val view = layoutInflater.inflate(R.layout.dialog_count_buy, null)
|
val view = layoutInflater.inflate(R.layout.dialog_count_buy, null)
|
||||||
@ -377,10 +389,9 @@ class DetailProductActivity : AppCompatActivity() {
|
|||||||
switchWholesale.visibility = View.VISIBLE
|
switchWholesale.visibility = View.VISIBLE
|
||||||
Toast.makeText(this, "Minimal pembelian grosir $currentQuantity produk", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, "Minimal pembelian grosir $currentQuantity produk", Toast.LENGTH_SHORT).show()
|
||||||
} else {
|
} else {
|
||||||
|
titleWholesale.visibility = View.GONE
|
||||||
switchWholesale.visibility = View.GONE
|
switchWholesale.visibility = View.GONE
|
||||||
}
|
}
|
||||||
// Set initial quantity based on current selection
|
|
||||||
|
|
||||||
|
|
||||||
switchWholesale.setOnCheckedChangeListener { _, isChecked ->
|
switchWholesale.setOnCheckedChangeListener { _, isChecked ->
|
||||||
isWholesaleSelected = isChecked
|
isWholesaleSelected = isChecked
|
||||||
|
@ -2,6 +2,7 @@ package com.alya.ecommerce_serang.ui.product
|
|||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
@ -35,7 +36,16 @@ class OtherProductAdapter (
|
|||||||
|
|
||||||
tvProductName.text = product.name
|
tvProductName.text = product.name
|
||||||
tvProductPrice.text = formatCurrency(product.price.toDouble())
|
tvProductPrice.text = formatCurrency(product.price.toDouble())
|
||||||
rating.text = product.rating
|
val ratingStr = product.rating
|
||||||
|
val ratingValue = ratingStr?.toFloatOrNull()
|
||||||
|
|
||||||
|
if (ratingValue != null && ratingValue > 0f) {
|
||||||
|
binding.rating.text = String.format("%.1f", ratingValue)
|
||||||
|
binding.rating.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
binding.rating.text = "Belum ada rating"
|
||||||
|
binding.rating.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null)
|
||||||
|
}
|
||||||
|
|
||||||
// Load image using Glide
|
// Load image using Glide
|
||||||
Glide.with(itemView)
|
Glide.with(itemView)
|
||||||
|
@ -128,7 +128,6 @@ class StoreDetailActivity : AppCompatActivity() {
|
|||||||
private fun updateStoreInfo(store: StoreItem?) {
|
private fun updateStoreInfo(store: StoreItem?) {
|
||||||
store?.let {
|
store?.let {
|
||||||
binding.tvStoreName.text = it.storeName
|
binding.tvStoreName.text = it.storeName
|
||||||
binding.tvStoreRating.text = it.storeRating
|
|
||||||
binding.tvStoreLocation.text = it.storeLocation
|
binding.tvStoreLocation.text = it.storeLocation
|
||||||
binding.tvStoreType.text = it.storeType
|
binding.tvStoreType.text = it.storeType
|
||||||
binding.tvActiveStatus.text = it.status
|
binding.tvActiveStatus.text = it.status
|
||||||
@ -145,6 +144,17 @@ class StoreDetailActivity : AppCompatActivity() {
|
|||||||
.load(fullImageUrl)
|
.load(fullImageUrl)
|
||||||
.placeholder(R.drawable.placeholder_image)
|
.placeholder(R.drawable.placeholder_image)
|
||||||
.into(binding.ivStoreImage)
|
.into(binding.ivStoreImage)
|
||||||
|
|
||||||
|
val ratingStr = it.storeRating
|
||||||
|
val ratingValue = ratingStr?.toFloatOrNull()
|
||||||
|
|
||||||
|
if (ratingValue != null && ratingValue > 0f) {
|
||||||
|
binding.tvStoreRating.text = String.format("%.1f", ratingValue)
|
||||||
|
binding.tvStoreRating.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
binding.tvStoreRating.text = "Belum ada rating"
|
||||||
|
binding.tvStoreRating.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import androidx.activity.viewModels
|
|||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.graphics.drawable.toDrawable
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
@ -36,8 +37,6 @@ import com.alya.ecommerce_serang.ui.order.address.ProvinceAdapter
|
|||||||
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
||||||
import com.alya.ecommerce_serang.utils.SessionManager
|
import com.alya.ecommerce_serang.utils.SessionManager
|
||||||
import com.alya.ecommerce_serang.utils.viewmodel.RegisterStoreViewModel
|
import com.alya.ecommerce_serang.utils.viewmodel.RegisterStoreViewModel
|
||||||
import androidx.core.graphics.drawable.toDrawable
|
|
||||||
import androidx.core.widget.ImageViewCompat
|
|
||||||
|
|
||||||
class RegisterStoreActivity : AppCompatActivity() {
|
class RegisterStoreActivity : AppCompatActivity() {
|
||||||
|
|
||||||
@ -157,7 +156,7 @@ class RegisterStoreActivity : AppCompatActivity() {
|
|||||||
!viewModel.bankName.value.isNullOrBlank() &&
|
!viewModel.bankName.value.isNullOrBlank() &&
|
||||||
(viewModel.bankNumber.value ?: 0) > 0 &&
|
(viewModel.bankNumber.value ?: 0) > 0 &&
|
||||||
(viewModel.provinceId.value ?: 0) > 0 &&
|
(viewModel.provinceId.value ?: 0) > 0 &&
|
||||||
(viewModel.cityId.value ?: 0) > 0 &&
|
!viewModel.cityId.value.isNullOrBlank() &&
|
||||||
(viewModel.storeTypeId.value ?: 0) > 0 &&
|
(viewModel.storeTypeId.value ?: 0) > 0 &&
|
||||||
viewModel.ktpUri != null &&
|
viewModel.ktpUri != null &&
|
||||||
viewModel.nibUri != null &&
|
viewModel.nibUri != null &&
|
||||||
|
@ -42,7 +42,7 @@ class RegisterStoreViewModel(
|
|||||||
val citiesState: LiveData<Result<List<CitiesItem>>> = _citiesState
|
val citiesState: LiveData<Result<List<CitiesItem>>> = _citiesState
|
||||||
|
|
||||||
var selectedProvinceId: Int? = null
|
var selectedProvinceId: Int? = null
|
||||||
var selectedCityId: Int? = null
|
var selectedCityId: String? = null
|
||||||
|
|
||||||
// Form fields
|
// Form fields
|
||||||
val storeName = MutableLiveData<String>()
|
val storeName = MutableLiveData<String>()
|
||||||
@ -52,7 +52,7 @@ class RegisterStoreViewModel(
|
|||||||
val longitude = MutableLiveData<String>()
|
val longitude = MutableLiveData<String>()
|
||||||
val street = MutableLiveData<String>()
|
val street = MutableLiveData<String>()
|
||||||
val subdistrict = MutableLiveData<String>()
|
val subdistrict = MutableLiveData<String>()
|
||||||
val cityId = MutableLiveData<Int>()
|
val cityId = MutableLiveData<String>()
|
||||||
val provinceId = MutableLiveData<Int>()
|
val provinceId = MutableLiveData<Int>()
|
||||||
val postalCode = MutableLiveData<Int>()
|
val postalCode = MutableLiveData<Int>()
|
||||||
val addressDetail = MutableLiveData<String>()
|
val addressDetail = MutableLiveData<String>()
|
||||||
@ -122,7 +122,7 @@ class RegisterStoreViewModel(
|
|||||||
longitude = longitude.value ?: "",
|
longitude = longitude.value ?: "",
|
||||||
street = street.value ?: "",
|
street = street.value ?: "",
|
||||||
subdistrict = subdistrict.value ?: "",
|
subdistrict = subdistrict.value ?: "",
|
||||||
cityId = cityId.value ?: 0,
|
cityId = cityId.value ?: "",
|
||||||
provinceId = provinceId.value ?: 0,
|
provinceId = provinceId.value ?: 0,
|
||||||
postalCode = postalCode.value ?: 0,
|
postalCode = postalCode.value ?: 0,
|
||||||
detail = addressDetail.value ?: "",
|
detail = addressDetail.value ?: "",
|
||||||
|
@ -16,6 +16,8 @@ import com.alya.ecommerce_serang.data.api.response.auth.User
|
|||||||
import com.alya.ecommerce_serang.data.api.response.auth.VerifRegisterResponse
|
import com.alya.ecommerce_serang.data.api.response.auth.VerifRegisterResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.customer.order.CitiesItem
|
import com.alya.ecommerce_serang.data.api.response.customer.order.CitiesItem
|
||||||
import com.alya.ecommerce_serang.data.api.response.customer.order.ProvincesItem
|
import com.alya.ecommerce_serang.data.api.response.customer.order.ProvincesItem
|
||||||
|
import com.alya.ecommerce_serang.data.api.response.customer.order.SubdistrictsItem
|
||||||
|
import com.alya.ecommerce_serang.data.api.response.customer.order.VillagesItem
|
||||||
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.api.retrofit.ApiService
|
||||||
import com.alya.ecommerce_serang.data.repository.OrderRepository
|
import com.alya.ecommerce_serang.data.repository.OrderRepository
|
||||||
@ -64,15 +66,24 @@ class RegisterViewModel(private val repository: UserRepository, private val orde
|
|||||||
|
|
||||||
// For address data
|
// For address data
|
||||||
var selectedProvinceId: Int? = null
|
var selectedProvinceId: Int? = null
|
||||||
var selectedCityId: Int? = null
|
var selectedCityId: String? = null
|
||||||
|
var selectedSubdistrict: String? = null
|
||||||
|
var selectedVillages: String? = null
|
||||||
|
var selectedPostalCode: String? = null
|
||||||
|
|
||||||
// For provinces and cities
|
// For provinces and cities using raja ongkir
|
||||||
private val _provincesState = MutableLiveData<ViewState<List<ProvincesItem>>>()
|
private val _provincesState = MutableLiveData<ViewState<List<ProvincesItem>>>()
|
||||||
val provincesState: LiveData<ViewState<List<ProvincesItem>>> = _provincesState
|
val provincesState: LiveData<ViewState<List<ProvincesItem>>> = _provincesState
|
||||||
|
|
||||||
private val _citiesState = MutableLiveData<ViewState<List<CitiesItem>>>()
|
private val _citiesState = MutableLiveData<ViewState<List<CitiesItem>>>()
|
||||||
val citiesState: LiveData<ViewState<List<CitiesItem>>> = _citiesState
|
val citiesState: LiveData<ViewState<List<CitiesItem>>> = _citiesState
|
||||||
|
|
||||||
|
private val _subdistrictState = MutableLiveData<ViewState<List<SubdistrictsItem>>>()
|
||||||
|
val subdistrictState: LiveData<ViewState<List<SubdistrictsItem>>> = _subdistrictState
|
||||||
|
|
||||||
|
private val _villagesState = MutableLiveData<ViewState<List<VillagesItem>>>()
|
||||||
|
val villagesState: LiveData<ViewState<List<VillagesItem>>> = _villagesState
|
||||||
|
|
||||||
// For address submission
|
// For address submission
|
||||||
private val _addressSubmissionState = MutableLiveData<ViewState<String>>()
|
private val _addressSubmissionState = MutableLiveData<ViewState<String>>()
|
||||||
val addressSubmissionState: LiveData<ViewState<String>> = _addressSubmissionState
|
val addressSubmissionState: LiveData<ViewState<String>> = _addressSubmissionState
|
||||||
@ -222,7 +233,7 @@ class RegisterViewModel(private val repository: UserRepository, private val orde
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//using raja ongkir
|
||||||
fun getProvinces() {
|
fun getProvinces() {
|
||||||
_provincesState.value = ViewState.Loading
|
_provincesState.value = ViewState.Loading
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
@ -242,6 +253,7 @@ class RegisterViewModel(private val repository: UserRepository, private val orde
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//kota pake raja ongkir
|
||||||
fun getCities(provinceId: Int) {
|
fun getCities(provinceId: Int) {
|
||||||
_citiesState.value = ViewState.Loading
|
_citiesState.value = ViewState.Loading
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
@ -263,14 +275,64 @@ class RegisterViewModel(private val repository: UserRepository, private val orde
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getSubdistrict(cityId: String) {
|
||||||
|
_subdistrictState.value = ViewState.Loading
|
||||||
|
viewModelScope.launch {
|
||||||
|
try {
|
||||||
|
|
||||||
|
selectedSubdistrict = cityId
|
||||||
|
val result = repository.getListSubdistrict(cityId)
|
||||||
|
result?.let {
|
||||||
|
_subdistrictState.postValue(ViewState.Success(it.subdistricts))
|
||||||
|
Log.d(TAG, "Cities loaded for province $cityId: ${it.subdistricts.size}")
|
||||||
|
} ?: run {
|
||||||
|
_subdistrictState.postValue(ViewState.Error("Failed to load cities"))
|
||||||
|
Log.e(TAG, "City result was null for province $cityId")
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
_subdistrictState.postValue(ViewState.Error(e.message ?: "Error loading cities"))
|
||||||
|
Log.e(TAG, "Error fetching cities for province $cityId", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getVillages(subdistrictId: String) {
|
||||||
|
_villagesState.value = ViewState.Loading
|
||||||
|
viewModelScope.launch {
|
||||||
|
try {
|
||||||
|
|
||||||
|
selectedVillages = subdistrictId
|
||||||
|
val result = repository.getListVillages(subdistrictId)
|
||||||
|
result?.let {
|
||||||
|
_villagesState.postValue(ViewState.Success(it.villages))
|
||||||
|
Log.d(TAG, "Cities loaded for province $subdistrictId: ${it.villages.size}")
|
||||||
|
} ?: run {
|
||||||
|
_villagesState.postValue(ViewState.Error("Failed to load cities"))
|
||||||
|
Log.e(TAG, "City result was null for province $subdistrictId")
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
_villagesState.postValue(ViewState.Error(e.message ?: "Error loading cities"))
|
||||||
|
Log.e(TAG, "Error fetching cities for province $subdistrictId", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun setSelectedProvinceId(id: Int) {
|
fun setSelectedProvinceId(id: Int) {
|
||||||
selectedProvinceId = id
|
selectedProvinceId = id
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setSelectedCityId(id: Int) {
|
fun updateSelectedCityId(id: String) {
|
||||||
selectedCityId = id
|
selectedCityId = id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateSelectedSubdistrict(id: String){
|
||||||
|
selectedSubdistrict = id
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateSelectedVillages(id: String){
|
||||||
|
selectedVillages = id
|
||||||
|
}
|
||||||
|
|
||||||
fun addAddress(request: CreateAddressRequest) {
|
fun addAddress(request: CreateAddressRequest) {
|
||||||
Log.d(TAG, "Starting address submission process")
|
Log.d(TAG, "Starting address submission process")
|
||||||
_addressSubmissionState.value = ViewState.Loading
|
_addressSubmissionState.value = ViewState.Loading
|
||||||
@ -313,6 +375,4 @@ class RegisterViewModel(private val repository: UserRepository, private val orde
|
|||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "RegisterViewModel"
|
private const val TAG = "RegisterViewModel"
|
||||||
}
|
}
|
||||||
|
|
||||||
//require auth
|
|
||||||
}
|
}
|
@ -133,6 +133,7 @@
|
|||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:text="Nomor Rekening / Nomor HP *"
|
android:text="Nomor Rekening / Nomor HP *"
|
||||||
android:fontFamily="@font/dmsans_semibold"
|
android:fontFamily="@font/dmsans_semibold"
|
||||||
|
android:visibility="gone"
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
@ -145,6 +146,7 @@
|
|||||||
android:inputType="text"
|
android:inputType="text"
|
||||||
android:minHeight="50dp"
|
android:minHeight="50dp"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
|
android:visibility="gone"
|
||||||
android:padding="12dp" />
|
android:padding="12dp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -152,6 +154,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:text="Tanggal Pembayaran *"
|
android:text="Tanggal Pembayaran *"
|
||||||
|
android:visibility="gone"
|
||||||
android:fontFamily="@font/dmsans_semibold"
|
android:fontFamily="@font/dmsans_semibold"
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
@ -164,6 +167,7 @@
|
|||||||
android:drawableEnd="@drawable/ic_calendar"
|
android:drawableEnd="@drawable/ic_calendar"
|
||||||
android:drawablePadding="8dp"
|
android:drawablePadding="8dp"
|
||||||
android:hint="Pilih tanggal"
|
android:hint="Pilih tanggal"
|
||||||
|
android:visibility="gone"
|
||||||
android:minHeight="50dp"
|
android:minHeight="50dp"
|
||||||
android:padding="12dp" />
|
android:padding="12dp" />
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<ScrollView
|
<ScrollView
|
||||||
|
android:id="@+id/sv_address_register"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
app:layout_constraintBottom_toTopOf="@id/btn_register"
|
app:layout_constraintBottom_toTopOf="@id/btn_register"
|
||||||
@ -149,7 +150,7 @@
|
|||||||
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="Kecamatan / Desa"
|
android:text="Kecamatan"
|
||||||
android:textColor="@android:color/black"
|
android:textColor="@android:color/black"
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp" />
|
||||||
|
|
||||||
@ -157,18 +158,61 @@
|
|||||||
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:hint="Isi Kecamatan / Desa"
|
android:hint="Pilih Kecamatan"
|
||||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<AutoCompleteTextView
|
||||||
android:id="@+id/et_kecamatan"
|
android:id="@+id/autoCompleteKecamatan"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="none"
|
||||||
|
android:focusable="false"
|
||||||
|
android:clickable="true"
|
||||||
android:padding="12dp"
|
android:padding="12dp"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp" />
|
||||||
android:inputType="textCapWords" />
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progress_bar_kecamatan"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<!-- DESA / Kelurahan -->
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="Kelurahan / Desa"
|
||||||
|
android:textColor="@android:color/black"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:hint="Pilih Kelurahan / Desa"
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu">
|
||||||
|
|
||||||
|
<AutoCompleteTextView
|
||||||
|
android:id="@+id/autoCompleteDesa"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="none"
|
||||||
|
android:focusable="false"
|
||||||
|
android:clickable="true"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progress_bar_desa"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:visibility="gone" />
|
||||||
<!-- Kode Pos -->
|
<!-- Kode Pos -->
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@ -196,7 +240,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="24dp"
|
||||||
android:background="@drawable/bg_button_outline"
|
android:background="@drawable/bg_button_outline"
|
||||||
android:text="Previous"
|
android:text="Kembali"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textColor="@color/blue1"
|
android:textColor="@color/blue1"
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"/>
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"/>
|
||||||
@ -214,7 +258,8 @@
|
|||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent" />
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/sv_address_register"/>
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progress_bar"
|
android:id="@+id/progress_bar"
|
||||||
|
@ -118,12 +118,11 @@
|
|||||||
|
|
||||||
<!-- Cancellation Reasons -->
|
<!-- Cancellation Reasons -->
|
||||||
<string-array name="cancellation_reasons">
|
<string-array name="cancellation_reasons">
|
||||||
<item>Found a better price elsewhere</item>
|
<item>Menemukan harga yang lebih baik</item>
|
||||||
<item>Changed my mind about the product</item>
|
<item>Berubah pikiran dengan pilihan produk</item>
|
||||||
<item>Ordered the wrong item</item>
|
<item>Kesalahan membeli produk</item>
|
||||||
<item>Shipping time is too long</item>
|
<item>Alasan keuangan</item>
|
||||||
<item>Financial reasons</item>
|
<item>Lainnya</item>
|
||||||
<item>Other reason</item>
|
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Chat Activity -->
|
<!-- Chat Activity -->
|
||||||
|
Reference in New Issue
Block a user