mirror of
https://github.com/shaulascr/ecommerce_serang.git
synced 2025-08-12 18:22:22 +00:00
store address update
This commit is contained in:
@ -143,14 +143,14 @@ class AddressRepository(private val apiService: ApiService) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
val addressMap = HashMap<String, Any?>()
|
val addressMap = HashMap<String, Any?>()
|
||||||
addressMap["provinceId"] = provinceId
|
addressMap["province_id"] = provinceId
|
||||||
addressMap["provinceName"] = provinceName
|
addressMap["province_name"] = provinceName
|
||||||
addressMap["cityId"] = cityId
|
addressMap["city_id"] = cityId
|
||||||
addressMap["cityName"] = cityName
|
addressMap["city_name"] = cityName
|
||||||
addressMap["street"] = street
|
addressMap["street"] = street
|
||||||
addressMap["subdistrict"] = subdistrict
|
addressMap["subdistrict"] = subdistrict
|
||||||
addressMap["detail"] = detail
|
addressMap["detail"] = detail
|
||||||
addressMap["postalCode"] = postalCode
|
addressMap["postal_code"] = postalCode
|
||||||
addressMap["latitude"] = latitude
|
addressMap["latitude"] = latitude
|
||||||
addressMap["longitude"] = longitude
|
addressMap["longitude"] = longitude
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import androidx.activity.viewModels
|
|||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.alya.ecommerce_serang.BuildConfig
|
import com.alya.ecommerce_serang.BuildConfig
|
||||||
|
import com.alya.ecommerce_serang.R
|
||||||
import com.alya.ecommerce_serang.data.api.dto.City
|
import com.alya.ecommerce_serang.data.api.dto.City
|
||||||
import com.alya.ecommerce_serang.data.api.dto.Province
|
import com.alya.ecommerce_serang.data.api.dto.Province
|
||||||
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
|
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
|
||||||
@ -28,6 +29,7 @@ class DetailStoreAddressActivity : AppCompatActivity() {
|
|||||||
private lateinit var sessionManager: SessionManager
|
private lateinit var sessionManager: SessionManager
|
||||||
|
|
||||||
private var selectedProvinceId: String? = null
|
private var selectedProvinceId: String? = null
|
||||||
|
private var selectedCityId: String? = null
|
||||||
private var provinces: List<Province> = emptyList()
|
private var provinces: List<Province> = emptyList()
|
||||||
private var cities: List<City> = emptyList()
|
private var cities: List<City> = emptyList()
|
||||||
|
|
||||||
@ -66,6 +68,7 @@ class DetailStoreAddressActivity : AppCompatActivity() {
|
|||||||
setupSpinners()
|
setupSpinners()
|
||||||
setupObservers()
|
setupObservers()
|
||||||
setupSaveButton()
|
setupSaveButton()
|
||||||
|
setupFieldListeners()
|
||||||
|
|
||||||
// Add retry button
|
// Add retry button
|
||||||
binding.btnRetry.setOnClickListener {
|
binding.btnRetry.setOnClickListener {
|
||||||
@ -95,17 +98,25 @@ class DetailStoreAddressActivity : AppCompatActivity() {
|
|||||||
if (position > 0 && provinces.isNotEmpty()) {
|
if (position > 0 && provinces.isNotEmpty()) {
|
||||||
selectedProvinceId = provinces[position - 1].provinceId
|
selectedProvinceId = provinces[position - 1].provinceId
|
||||||
Log.d(TAG, "Selected province ID: $selectedProvinceId")
|
Log.d(TAG, "Selected province ID: $selectedProvinceId")
|
||||||
selectedProvinceId?.let {
|
selectedCityId = null
|
||||||
Log.d(TAG, "Fetching cities for province ID: $it")
|
showCityLoading(true)
|
||||||
showCityLoading(true)
|
viewModel.fetchCities(selectedProvinceId!!)
|
||||||
viewModel.fetchCities(it)
|
} else {
|
||||||
}
|
selectedProvinceId = null
|
||||||
}
|
}
|
||||||
|
checkAllFieldsFilled()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNothingSelected(p0: AdapterView<*>?) {
|
override fun onNothingSelected(p0: AdapterView<*>?) {}
|
||||||
// Do nothing
|
}
|
||||||
|
|
||||||
|
binding.spinnerCity.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
|
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||||
|
selectedCityId = if (position > 0) cities[position - 1].cityId else null
|
||||||
|
checkAllFieldsFilled()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onNothingSelected(p0: AdapterView<*>?) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,11 +126,6 @@ class DetailStoreAddressActivity : AppCompatActivity() {
|
|||||||
Log.d(TAG, "Received provinces: ${provinceList.size}")
|
Log.d(TAG, "Received provinces: ${provinceList.size}")
|
||||||
showProvinceLoading(false)
|
showProvinceLoading(false)
|
||||||
|
|
||||||
if (provinceList.isEmpty()) {
|
|
||||||
showError("No provinces available")
|
|
||||||
return@observe
|
|
||||||
}
|
|
||||||
|
|
||||||
provinces = provinceList
|
provinces = provinceList
|
||||||
val provinceNames = mutableListOf("Pilih Provinsi")
|
val provinceNames = mutableListOf("Pilih Provinsi")
|
||||||
provinceNames.addAll(provinceList.map { it.provinceName })
|
provinceNames.addAll(provinceList.map { it.provinceName })
|
||||||
@ -133,6 +139,13 @@ class DetailStoreAddressActivity : AppCompatActivity() {
|
|||||||
)
|
)
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
binding.spinnerProvince.adapter = adapter
|
binding.spinnerProvince.adapter = adapter
|
||||||
|
|
||||||
|
viewModel.storeAddress.value?.let { address ->
|
||||||
|
val index = provinces.indexOfFirst { it.provinceId == address.provinceId }
|
||||||
|
if (index != -1) {
|
||||||
|
binding.spinnerProvince.setSelection(index + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Observe cities data
|
// Observe cities data
|
||||||
@ -156,14 +169,9 @@ class DetailStoreAddressActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
// If we have a stored city_id, select it
|
// If we have a stored city_id, select it
|
||||||
viewModel.storeAddress.value?.let { address ->
|
viewModel.storeAddress.value?.let { address ->
|
||||||
if (address.cityId.isNotEmpty()) {
|
val index = cities.indexOfFirst { it.cityId == address.cityId }
|
||||||
val cityIndex = cities.indexOfFirst { city ->
|
if (index != -1) {
|
||||||
city.cityId == address.cityId
|
binding.spinnerCity.setSelection(index + 1)
|
||||||
}
|
|
||||||
Log.d(TAG, "City index for ID ${address.cityId}: $cityIndex")
|
|
||||||
if (cityIndex != -1) {
|
|
||||||
binding.spinnerCity.setSelection(cityIndex + 1) // +1 because of "Pilih Kota/Kabupaten"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,54 +181,41 @@ class DetailStoreAddressActivity : AppCompatActivity() {
|
|||||||
Log.d(TAG, "Received store address: $address")
|
Log.d(TAG, "Received store address: $address")
|
||||||
address?.let {
|
address?.let {
|
||||||
// Set the fields
|
// Set the fields
|
||||||
binding.edtStreet.setText(address.street)
|
binding.edtStreet.setText(it.street)
|
||||||
binding.edtSubdistrict.setText(address.subdistrict)
|
binding.edtSubdistrict.setText(it.subdistrict)
|
||||||
binding.edtDetailAddress.setText(address.detail ?: "")
|
binding.edtDetailAddress.setText(it.detail ?: "")
|
||||||
binding.edtPostalCode.setText(address.postalCode)
|
binding.edtPostalCode.setText(it.postalCode)
|
||||||
|
binding.edtLatitude.setText(it.latitude.toString())
|
||||||
|
binding.edtLongitude.setText(it.longitude.toString())
|
||||||
|
selectedProvinceId = it.provinceId
|
||||||
|
selectedCityId = it.cityId
|
||||||
|
|
||||||
// Handle latitude and longitude
|
// Find province index and select it after provinces are loaded
|
||||||
val lat = if (address.latitude == null || address.latitude.toString() == "NaN") 0.0 else address.latitude
|
if (provinces.isNotEmpty()) {
|
||||||
val lng = if (address.longitude == null || address.longitude.toString() == "NaN") 0.0 else address.longitude
|
val index = provinces.indexOfFirst { p -> p.provinceId == it.provinceId }
|
||||||
|
Log.d(TAG, "Province index for ID ${address.provinceId}: $index")
|
||||||
binding.edtLatitude.setText(lat.toString())
|
if (index != -1) {
|
||||||
binding.edtLongitude.setText(lng.toString())
|
binding.spinnerProvince.setSelection(index + 1) // +1 because of "Pilih Provinsi"
|
||||||
|
// showCityLoading(true)
|
||||||
// Set selected province ID to trigger city loading
|
viewModel.fetchCities(it.provinceId)
|
||||||
if (address.provinceId.isNotEmpty()) {
|
|
||||||
selectedProvinceId = address.provinceId
|
|
||||||
|
|
||||||
// Find province index and select it after provinces are loaded
|
|
||||||
if (provinces.isNotEmpty()) {
|
|
||||||
val provinceIndex = provinces.indexOfFirst { province ->
|
|
||||||
province.provinceId == address.provinceId
|
|
||||||
}
|
|
||||||
Log.d(TAG, "Province index for ID ${address.provinceId}: $provinceIndex")
|
|
||||||
if (provinceIndex != -1) {
|
|
||||||
binding.spinnerProvince.setSelection(provinceIndex + 1) // +1 because of "Pilih Provinsi"
|
|
||||||
|
|
||||||
// Now fetch cities for this province
|
|
||||||
showCityLoading(true)
|
|
||||||
viewModel.fetchCities(address.provinceId)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Observe loading state
|
// Observe loading state
|
||||||
viewModel.isLoading.observe(this) { isLoading ->
|
viewModel.isLoading.observe(this) {
|
||||||
binding.progressBar.visibility = if (isLoading) View.VISIBLE else View.GONE
|
binding.progressBar.visibility = if (it) View.VISIBLE else View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Observe error messages
|
// Observe error messages
|
||||||
viewModel.errorMessage.observe(this) { errorMsg ->
|
viewModel.errorMessage.observe(this) {
|
||||||
Log.e(TAG, "Error: $errorMsg")
|
showError(it)
|
||||||
showError(errorMsg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Observe save success
|
// Observe save success
|
||||||
viewModel.saveSuccess.observe(this) { success ->
|
viewModel.saveSuccess.observe(this) {
|
||||||
if (success) {
|
if (it) {
|
||||||
Toast.makeText(this, "Alamat berhasil disimpan", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, "Alamat berhasil disimpan", Toast.LENGTH_SHORT).show()
|
||||||
setResult(Activity.RESULT_OK)
|
setResult(Activity.RESULT_OK)
|
||||||
finish()
|
finish()
|
||||||
@ -228,6 +223,71 @@ class DetailStoreAddressActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setupSaveButton() {
|
||||||
|
binding.btnSaveAddress.setOnClickListener {
|
||||||
|
val street = binding.edtStreet.text.toString()
|
||||||
|
val subdistrict = binding.edtSubdistrict.text.toString()
|
||||||
|
val detail = binding.edtDetailAddress.text.toString()
|
||||||
|
val postalCode = binding.edtPostalCode.text.toString()
|
||||||
|
val latitude = binding.edtLatitude.text.toString().toDoubleOrNull() ?: 0.0
|
||||||
|
val longitude = binding.edtLongitude.text.toString().toDoubleOrNull() ?: 0.0
|
||||||
|
|
||||||
|
val city = cities.find { it.cityId == selectedCityId }
|
||||||
|
val province = provinces.find { it.provinceId == selectedProvinceId }
|
||||||
|
|
||||||
|
// Validate required fields
|
||||||
|
if (selectedProvinceId.isNullOrEmpty() || city == null || street.isEmpty() || subdistrict.isEmpty() || postalCode.isEmpty()) {
|
||||||
|
Toast.makeText(this, "Mohon lengkapi data yang wajib diisi", Toast.LENGTH_SHORT).show()
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save address
|
||||||
|
viewModel.saveStoreAddress(
|
||||||
|
provinceId = selectedProvinceId!!,
|
||||||
|
provinceName = province?.provinceName ?: "",
|
||||||
|
cityId = city.cityId,
|
||||||
|
cityName = city.cityName,
|
||||||
|
street = street,
|
||||||
|
subdistrict = subdistrict,
|
||||||
|
detail = detail,
|
||||||
|
postalCode = postalCode,
|
||||||
|
latitude = latitude,
|
||||||
|
longitude = longitude
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupFieldListeners() {
|
||||||
|
val watcher = object : android.text.TextWatcher {
|
||||||
|
override fun afterTextChanged(s: android.text.Editable?) = checkAllFieldsFilled()
|
||||||
|
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||||
|
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
||||||
|
}
|
||||||
|
binding.edtStreet.addTextChangedListener(watcher)
|
||||||
|
binding.edtSubdistrict.addTextChangedListener(watcher)
|
||||||
|
binding.edtPostalCode.addTextChangedListener(watcher)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkAllFieldsFilled() {
|
||||||
|
val allValid = !selectedProvinceId.isNullOrEmpty()
|
||||||
|
&& !selectedCityId.isNullOrEmpty()
|
||||||
|
&& binding.edtStreet.text.isNotBlank()
|
||||||
|
&& binding.edtSubdistrict.text.isNotBlank()
|
||||||
|
&& binding.edtPostalCode.text.isNotBlank()
|
||||||
|
|
||||||
|
binding.btnSaveAddress.let {
|
||||||
|
if (allValid) {
|
||||||
|
it.isEnabled = true
|
||||||
|
it.setBackgroundResource(R.drawable.bg_button_active)
|
||||||
|
it.setTextColor(getColor(R.color.white))
|
||||||
|
} else {
|
||||||
|
it.isEnabled = false
|
||||||
|
it.setBackgroundResource(R.drawable.bg_button_disabled)
|
||||||
|
it.setTextColor(getColor(R.color.black_300))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun showProvinceLoading(isLoading: Boolean) {
|
private fun showProvinceLoading(isLoading: Boolean) {
|
||||||
binding.provinceProgressBar.visibility = if (isLoading) View.VISIBLE else View.GONE
|
binding.provinceProgressBar.visibility = if (isLoading) View.VISIBLE else View.GONE
|
||||||
binding.spinnerProvince.visibility = if (isLoading) View.GONE else View.VISIBLE
|
binding.spinnerProvince.visibility = if (isLoading) View.GONE else View.VISIBLE
|
||||||
@ -244,7 +304,6 @@ class DetailStoreAddressActivity : AppCompatActivity() {
|
|||||||
binding.tvError.text = "Error: $message\nURL: ${BuildConfig.BASE_URL}/provinces"
|
binding.tvError.text = "Error: $message\nURL: ${BuildConfig.BASE_URL}/provinces"
|
||||||
binding.btnRetry.visibility = View.VISIBLE
|
binding.btnRetry.visibility = View.VISIBLE
|
||||||
|
|
||||||
// Also show in a dialog for immediate attention
|
|
||||||
AlertDialog.Builder(this)
|
AlertDialog.Builder(this)
|
||||||
.setTitle("Error")
|
.setTitle("Error")
|
||||||
.setMessage("$message\n\nAPI URL: ${BuildConfig.BASE_URL}/provinces")
|
.setMessage("$message\n\nAPI URL: ${BuildConfig.BASE_URL}/provinces")
|
||||||
@ -258,7 +317,6 @@ class DetailStoreAddressActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
.show()
|
.show()
|
||||||
|
|
||||||
// Also show a snackbar
|
|
||||||
Snackbar.make(binding.root, "Error: $message", Snackbar.LENGTH_LONG)
|
Snackbar.make(binding.root, "Error: $message", Snackbar.LENGTH_LONG)
|
||||||
.setAction("Retry") {
|
.setAction("Retry") {
|
||||||
binding.tvError.visibility = View.GONE
|
binding.tvError.visibility = View.GONE
|
||||||
@ -267,49 +325,4 @@ class DetailStoreAddressActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupSaveButton() {
|
|
||||||
binding.btnSaveAddress.setOnClickListener {
|
|
||||||
val street = binding.edtStreet.text.toString()
|
|
||||||
val subdistrict = binding.edtSubdistrict.text.toString()
|
|
||||||
val detail = binding.edtDetailAddress.text.toString()
|
|
||||||
val postalCode = binding.edtPostalCode.text.toString()
|
|
||||||
val latitudeStr = binding.edtLatitude.text.toString()
|
|
||||||
val longitudeStr = binding.edtLongitude.text.toString()
|
|
||||||
|
|
||||||
// Validate required fields
|
|
||||||
if (selectedProvinceId == null || binding.spinnerCity.selectedItemPosition <= 0 ||
|
|
||||||
street.isEmpty() || subdistrict.isEmpty() || postalCode.isEmpty()) {
|
|
||||||
Toast.makeText(this, "Mohon lengkapi data yang wajib diisi", Toast.LENGTH_SHORT).show()
|
|
||||||
return@setOnClickListener
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get selected city
|
|
||||||
val cityPosition = binding.spinnerCity.selectedItemPosition
|
|
||||||
if (cityPosition <= 0 || cities.isEmpty() || cityPosition > cities.size) {
|
|
||||||
Toast.makeText(this, "Mohon pilih kota/kabupaten", Toast.LENGTH_SHORT).show()
|
|
||||||
return@setOnClickListener
|
|
||||||
}
|
|
||||||
|
|
||||||
val selectedCity = cities[cityPosition - 1]
|
|
||||||
|
|
||||||
// Parse coordinates
|
|
||||||
val latitude = latitudeStr.toDoubleOrNull() ?: 0.0
|
|
||||||
val longitude = longitudeStr.toDoubleOrNull() ?: 0.0
|
|
||||||
|
|
||||||
// Save address
|
|
||||||
viewModel.saveStoreAddress(
|
|
||||||
provinceId = selectedProvinceId!!,
|
|
||||||
provinceName = provinces.find { it.provinceId == selectedProvinceId }?.provinceName ?: "",
|
|
||||||
cityId = selectedCity.cityId,
|
|
||||||
cityName = selectedCity.cityName,
|
|
||||||
street = street,
|
|
||||||
subdistrict = subdistrict,
|
|
||||||
detail = detail,
|
|
||||||
postalCode = postalCode,
|
|
||||||
latitude = latitude,
|
|
||||||
longitude = longitude
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -351,8 +351,8 @@
|
|||||||
<Button
|
<Button
|
||||||
android:id="@+id/btn_save_address"
|
android:id="@+id/btn_save_address"
|
||||||
android:text="Simpan Perubahan"
|
android:text="Simpan Perubahan"
|
||||||
style="@style/button.large.disabled.long"
|
style="@style/button.large.active.long"
|
||||||
android:enabled="false"
|
android:enabled="true"
|
||||||
android:layout_marginBottom="16dp"/>
|
android:layout_marginBottom="16dp"/>
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
|
Reference in New Issue
Block a user