From ff8654d12aafce1df926d544ffbd302e6b4e8d7d Mon Sep 17 00:00:00 2001 From: shaulascr Date: Mon, 18 Aug 2025 16:01:07 +0700 Subject: [PATCH 1/4] fix wholesale price and edit profile --- .../ecommerce_serang/ui/cart/CartActivity.kt | 14 ++++++-- .../ui/order/CheckoutActivity.kt | 21 +++++------ .../ui/order/CheckoutViewModel.kt | 35 +++++++++++-------- .../ui/order/SingleItemCartAdapter.kt | 2 ++ .../editprofile/EditProfileCustActivity.kt | 21 ++++++----- 5 files changed, 54 insertions(+), 39 deletions(-) diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/cart/CartActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/cart/CartActivity.kt index b5fba26..3df50c8 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/cart/CartActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/cart/CartActivity.kt @@ -151,7 +151,7 @@ class CartActivity : AppCompatActivity() { // Debug log Log.d( - TAG, + TAG, "cartItemId: ${updatedCartItem.cartItemId}, " + "isWholesale: ${info.isWholesale}, " + "wholesalePrice: $wholesalePrice, " + @@ -164,7 +164,17 @@ class CartActivity : AppCompatActivity() { val cartItemIds = updatedItems.map { it.cartItem.cartItemId } val wholesaleArray = updatedItems.map { it.isWholesale }.toBooleanArray() - CheckoutActivity.startForCart(this, cartItemIds, wholesaleArray) + // FIX: Pass wholesale prices as IntArray + val wholesalePricesArray = updatedItems.map { info -> + if (info.isWholesale) { + val wholesalePrice = wholesalePriceMap[info.cartItem.cartItemId] + wholesalePrice?.toInt() ?: info.cartItem.price + } else { + info.cartItem.price + } + }.toIntArray() + + CheckoutActivity.startForCart(this, cartItemIds, wholesaleArray, wholesalePricesArray) } private fun observeViewModel() { diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/CheckoutActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/CheckoutActivity.kt index 91ba62d..127a1d6 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/CheckoutActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/CheckoutActivity.kt @@ -79,9 +79,6 @@ class CheckoutActivity : AppCompatActivity() { // Determine if this is Buy Now or Cart checkout val isBuyNow = intent.hasExtra(EXTRA_PRODUCT_ID) && !intent.hasExtra(EXTRA_CART_ITEM_IDS) val isWholesaleNow = intent.getBooleanExtra(EXTRA_ISWHOLESALE, false) - val wholesalePricesArray = intent.getIntArrayExtra(EXTRA_CART_ITEM_WHOLESALE_PRICES) - - if (isBuyNow) { // Process Buy Now flow @@ -99,8 +96,7 @@ class CheckoutActivity : AppCompatActivity() { // Process Cart checkout flow val cartItemIds = intent.getIntArrayExtra(EXTRA_CART_ITEM_IDS)?.toList() ?: emptyList() val isWholesaleArray = intent.getBooleanArrayExtra(EXTRA_CART_ITEM_WHOLESALE) - - + val wholesalePricesArray = intent.getIntArrayExtra(EXTRA_CART_ITEM_WHOLESALE_PRICES) if (cartItemIds.isNotEmpty()) { // Build map of cartItemId -> isWholesale @@ -108,17 +104,18 @@ class CheckoutActivity : AppCompatActivity() { cartItemIds.mapIndexed { index, id -> id to isWholesaleArray[index] }.toMap() - - } else { emptyMap() } - - // Build wholesalePriceMap - val wholesalePriceMap = cartItemIds.mapIndexed { index, id -> - id to (wholesalePricesArray?.get(index) ?: 0) - }.toMap() + // Build wholesalePriceMap - FIX: Map cartItemId to wholesale price + val wholesalePriceMap = if (wholesalePricesArray != null && wholesalePricesArray.size == cartItemIds.size) { + cartItemIds.mapIndexed { index, id -> + id to wholesalePricesArray[index] + }.toMap() + } else { + emptyMap() + } viewModel.initializeFromCart( cartItemIds, diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/CheckoutViewModel.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/CheckoutViewModel.kt index b11620a..f263122 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/CheckoutViewModel.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/CheckoutViewModel.kt @@ -96,7 +96,7 @@ class CheckoutViewModel(private val repository: OrderRepository) : ViewModel() { fun initializeFromCart( cartItemIds: List, isWholesaleMap: Map = emptyMap(), - wholesalePriceMap: Map = emptyMap() // new + wholesalePriceMap: Map = emptyMap() ) { viewModelScope.launch { _isLoading.value = true @@ -111,13 +111,21 @@ class CheckoutViewModel(private val repository: OrderRepository) : ViewModel() { for (store in cartResult.data) { val storeItems = store.cartItems.filter { it.cartItemId in cartItemIds } if (storeItems.isNotEmpty()) { - // ✅ Override price with wholesale price if exists + // ✅ Apply wholesale prices - Replace item prices with wholesale prices val updatedItems = storeItems.map { item -> val wholesalePrice = wholesalePriceMap[item.cartItemId] - if (wholesalePrice != null) { - item.copy(price = wholesalePrice.toInt()) - } else item + val isWholesale = isWholesaleMap[item.cartItemId] ?: false + + // Use wholesale price if item is wholesale and price exists + if (isWholesale && wholesalePrice != null) { + Log.d(TAG, "Applying wholesale price for item ${item.cartItemId}: ${item.price} -> $wholesalePrice") + item.copy(price = wholesalePrice) + } else { + Log.d(TAG, "Using regular price for item ${item.cartItemId}: ${item.price}") + item + } } + matchingItems.addAll(updatedItems) storeData = store break @@ -143,16 +151,17 @@ class CheckoutViewModel(private val repository: OrderRepository) : ViewModel() { sellerName = storeData.storeName, sellerId = storeData.storeId, isBuyNow = false, - cartItems = matchingItems, + cartItems = matchingItems, // These now have updated wholesale prices cartItemWholesaleMap = isWholesaleMap ) - Log.d(TAG, "CheckoutData initialized: ${_checkoutData.value}") - Log.d(TAG, "Matching cart items: ${matchingItems.size}") - Log.d(TAG, "Cart items: ${matchingItems.map { it.productName to it.price }}") - Log.d(TAG, "IsWholesaleMap passed: $isWholesaleMap") - Log.d(TAG, "WholesalePriceMap passed: $wholesalePriceMap") + Log.d(TAG, "CheckoutData initialized with ${matchingItems.size} items") + matchingItems.forEachIndexed { index, item -> + val isWholesale = isWholesaleMap[item.cartItemId] ?: false + Log.d(TAG, "Item $index: ${item.productName}, Price: ${item.price}, IsWholesale: $isWholesale") + } + // Calculate totals with updated prices calculateSubtotal() calculateTotal() } else { @@ -163,11 +172,11 @@ class CheckoutViewModel(private val repository: OrderRepository) : ViewModel() { } } catch (e: Exception) { _errorMessage.value = "Error: ${e.message}" + Log.e(TAG, "Error in initializeFromCart", e) } finally { _isLoading.value = false } } - } fun getPaymentMethods() { @@ -418,8 +427,6 @@ class CheckoutViewModel(private val repository: OrderRepository) : ViewModel() { } } - - companion object { private const val TAG = "CheckoutViewModel" } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/SingleItemCartAdapter.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/SingleItemCartAdapter.kt index e5872a3..753eef3 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/SingleItemCartAdapter.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/SingleItemCartAdapter.kt @@ -34,6 +34,8 @@ class SingleCartItemAdapter(private val cartItem: CartItemsItem) : // Load placeholder image Glide.with(ivProduct.context) .load(R.drawable.placeholder_image) + .placeholder(R.drawable.placeholder_image) + .error(R.drawable.placeholder_image) .into(ivProduct) } } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/editprofile/EditProfileCustActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/editprofile/EditProfileCustActivity.kt index 9a7f3e2..1b17534 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/editprofile/EditProfileCustActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/editprofile/EditProfileCustActivity.kt @@ -1,10 +1,12 @@ package com.alya.ecommerce_serang.ui.profile.editprofile +import android.Manifest import android.app.Activity import android.app.DatePickerDialog import android.content.Intent import android.content.pm.PackageManager import android.net.Uri +import android.os.Build import android.os.Bundle import android.provider.MediaStore import android.util.Log @@ -159,17 +161,14 @@ class EditProfileCustActivity : AppCompatActivity() { } private fun openImagePicker() { - // Check for permission first - if (ContextCompat.checkSelfPermission( - this, - android.Manifest.permission.READ_EXTERNAL_STORAGE - ) != PackageManager.PERMISSION_GRANTED - ) { - ActivityCompat.requestPermissions( - this, - arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE), - REQUEST_STORAGE_PERMISSION - ) + val permission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + Manifest.permission.READ_MEDIA_IMAGES + } else { + Manifest.permission.READ_EXTERNAL_STORAGE + } + + if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions(this, arrayOf(permission), REQUEST_STORAGE_PERMISSION) } else { launchImagePicker() } From 6baf4ee5ce10e3320243555f9a52dd88faca3d8d Mon Sep 17 00:00:00 2001 From: shaulascr Date: Tue, 19 Aug 2025 07:27:48 +0700 Subject: [PATCH 2/4] fix add address --- .../ui/order/address/AddAddressActivity.kt | 32 +++++++------------ .../ui/order/address/AddAddressViewModel.kt | 18 +++++++++++ .../ui/profile/mystore/sells/SellsAdapter.kt | 14 ++++---- app/src/main/res/layout/item_card_address.xml | 1 - 4 files changed, 37 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressActivity.kt index cd36fe7..8d524f7 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressActivity.kt @@ -22,7 +22,6 @@ import androidx.core.view.ViewCompat import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat import com.alya.ecommerce_serang.data.api.dto.CreateAddressRequest -import com.alya.ecommerce_serang.data.api.dto.UserProfile import com.alya.ecommerce_serang.data.api.response.customer.order.CitiesItem import com.alya.ecommerce_serang.data.api.response.customer.order.ProvincesItem import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig @@ -37,8 +36,8 @@ class AddAddressActivity : AppCompatActivity() { private lateinit var binding: ActivityAddAddressBinding private lateinit var apiService: ApiService private lateinit var sessionManager: SessionManager - private var profileUser: Int = 1 private lateinit var locationManager: LocationManager + private var profileUserId: Int? = null private var isRequestingLocation = false @@ -80,11 +79,15 @@ class AddAddressActivity : AppCompatActivity() { ) windowInsets } + viewModel.loadUserProfile() -// Get user profile from session manager -// profileUser =UserProfile. - viewModel.userProfile.observe(this){ user -> - user?.let { updateProfile(it) } + viewModel.userProfile.observe(this) { user -> + if (user != null) { + profileUserId = user.userId + Log.d(TAG, "Fetched userId = $profileUserId") // ✅ debug log + } else { + Log.e(TAG, "Error get profile") + } } setupToolbar() @@ -94,16 +97,10 @@ class AddAddressActivity : AppCompatActivity() { setupButtonListeners() setupObservers() - - // Force trigger province loading to ensure it happens viewModel.getProvinces() } - private fun updateProfile(userProfile: UserProfile){ - profileUser = userProfile.userId - } - // UI setup methods private fun setupToolbar() { binding.toolbar.setNavigationOnClickListener { @@ -280,12 +277,7 @@ class AddAddressActivity : AppCompatActivity() { val postalCode = binding.etKodePos.text.toString().trim() val recipient = binding.etNamaPenerima.text.toString().trim() val phone = binding.etNomorHp.text.toString().trim() - val userId = try { - profileUser - } catch (e: Exception) { - Log.w(TAG, "Error getting userId, using default", e) - 1 // Default userId for testing - } + val userId = profileUserId val isStoreLocation = false val provinceId = viewModel.selectedProvinceId @@ -333,7 +325,7 @@ class AddAddressActivity : AppCompatActivity() { // Create request with all fields val request = CreateAddressRequest( - userId = userId, + userId = userId!!, lat = latitude!!, // Safe to use !! as we've checked above long = longitude!!, street = street, @@ -525,6 +517,6 @@ class AddAddressActivity : AppCompatActivity() { } companion object { - private const val TAG = "AddAddressViewModel" + private const val TAG = "AddAddressActivity" } } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressViewModel.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressViewModel.kt index dedb63a..d7790a1 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressViewModel.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressViewModel.kt @@ -252,6 +252,24 @@ class AddAddressViewModel(private val repository: OrderRepository, private val u return params } + fun loadUserProfile() { + viewModelScope.launch { + when (val result = repository.fetchUserProfile()) { + is Result.Success -> { + result.data?.let { + _userProfile.postValue(it) // send UserProfile to LiveData + } ?: _errorMessageUser.postValue("User data not found") + } + is Result.Error -> { + _errorMessageUser.postValue(result.exception.message ?: "Unknown error") + } + is Result.Loading -> { + null + } + } + } + } + companion object { private const val TAG = "AddAddressViewModel" } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/SellsAdapter.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/SellsAdapter.kt index 38342be..8765e20 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/SellsAdapter.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/SellsAdapter.kt @@ -17,6 +17,7 @@ import com.alya.ecommerce_serang.ui.profile.mystore.sells.shipment.DetailShipmen import com.alya.ecommerce_serang.utils.viewmodel.SellsViewModel import com.bumptech.glide.Glide import com.google.gson.Gson +import java.text.NumberFormat import java.text.SimpleDateFormat import java.util.Calendar import java.util.Locale @@ -96,7 +97,7 @@ class SellsAdapter( val product = order.orderItems?.firstOrNull() tvSellsProductName.text = product?.productName tvSellsProductQty.text = "x${product?.quantity}" - tvSellsProductPrice.text = formatPrice(product?.price.toString()) + tvSellsProductPrice.text = product?.price?.let { formatPrice(it.toInt()) } val fullImageUrl = when (val img = product?.productImage) { is String -> { @@ -169,7 +170,7 @@ class SellsAdapter( val product = order.orderItems?.firstOrNull() tvSellsProductName.text = product?.productName tvSellsProductQty.text = "x${product?.quantity}" - tvSellsProductPrice.text = formatPrice(product?.price.toString()) + tvSellsProductPrice.text = product?.price?.let { formatPrice(it.toInt()) } val fullImageUrl = when (val img = product?.productImage) { is String -> { @@ -185,7 +186,7 @@ class SellsAdapter( .into(ivSellsProduct) tvSellsQty.text = "${order.orderItems?.size} produk" - tvSellsPrice.text = formatPrice(order.totalAmount.toString()) + tvSellsPrice.text = order.totalAmount?.let { formatPrice(it.toInt()) } } "paid" -> { layoutOrders.visibility = View.GONE @@ -308,10 +309,9 @@ class SellsAdapter( } } - private fun formatPrice(price: String): String { - val priceDouble = price.toDoubleOrNull() ?: 0.0 - val formattedPrice = String.format(Locale("id", "ID"), "Rp%,.0f", priceDouble) - return formattedPrice + private fun formatPrice(amount: Int): String { + val formatter = NumberFormat.getCurrencyInstance(Locale("in", "ID")) + return formatter.format(amount.toLong()).replace(",00", "") } } } \ No newline at end of file diff --git a/app/src/main/res/layout/item_card_address.xml b/app/src/main/res/layout/item_card_address.xml index cee554f..716a59c 100644 --- a/app/src/main/res/layout/item_card_address.xml +++ b/app/src/main/res/layout/item_card_address.xml @@ -38,7 +38,6 @@ android:src="@drawable/baseline_edit_24" android:focusable="true" android:clickable="true" - android:visibility="gone" android:layout_marginHorizontal="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent"/> From b6b701fa3b41153df4e3f992ff46e79c739be4cf Mon Sep 17 00:00:00 2001 From: shaulascr Date: Wed, 20 Aug 2025 00:52:56 +0700 Subject: [PATCH 3/4] fix add and edit address --- .../customer/profile/AddressDetailResponse.kt | 6 +- .../data/api/retrofit/ApiService.kt | 2 +- .../ui/order/address/AddAddressActivity.kt | 135 ++++++++++++++++-- .../ui/order/address/AddAddressViewModel.kt | 23 +-- .../ui/order/address/EditAddressActivity.kt | 52 ++++++- .../ui/order/address/ProvinceAdapter.kt | 12 ++ .../main/res/layout/activity_add_address.xml | 57 ++++++-- 7 files changed, 247 insertions(+), 40 deletions(-) diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/customer/profile/AddressDetailResponse.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/customer/profile/AddressDetailResponse.kt index b051263..885200d 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/customer/profile/AddressDetailResponse.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/customer/profile/AddressDetailResponse.kt @@ -23,13 +23,13 @@ data class AddressDetail( val latitude: String, @field:SerializedName("province_name") - val provinceName: String, + val provinceName: String?, @field:SerializedName("subdistrict_id") - val subdistrictId: String, + val subdistrictId: String?, @field:SerializedName("city_name") - val cityName: String, + val cityName: String?, @field:SerializedName("user_id") val userId: Int, diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/retrofit/ApiService.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/retrofit/ApiService.kt index 59250bb..cd4f41e 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/data/api/retrofit/ApiService.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/retrofit/ApiService.kt @@ -530,7 +530,7 @@ interface ApiService { @Body request: ResetPassReq ): Response - @GET("address/detail/{id}") + @GET("profile/address/detail/{id}") suspend fun getDetailAddress( @Path("id") addressId: Int ): Response diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressActivity.kt index 8d524f7..4b29f78 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressActivity.kt @@ -24,9 +24,12 @@ import androidx.core.view.WindowInsetsCompat import com.alya.ecommerce_serang.data.api.dto.CreateAddressRequest 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.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.ApiService import com.alya.ecommerce_serang.data.repository.OrderRepository +import com.alya.ecommerce_serang.data.repository.Result import com.alya.ecommerce_serang.data.repository.UserRepository import com.alya.ecommerce_serang.databinding.ActivityAddAddressBinding import com.alya.ecommerce_serang.utils.SavedStateViewModelFactory @@ -45,6 +48,8 @@ class AddAddressActivity : AppCompatActivity() { private var longitude: Double? = null private val provinceAdapter by lazy { ProvinceAdapter(this) } private val cityAdapter by lazy { CityAdapter(this) } + private val subdistrictAdapter by lazy { SubdsitrictAdapter(this)} + private val villageAdapter by lazy { VillagesAdapter(this)} private val viewModel: AddAddressViewModel by viewModels { SavedStateViewModelFactory(this) { savedStateHandle -> @@ -113,6 +118,8 @@ class AddAddressActivity : AppCompatActivity() { // Set adapters binding.autoCompleteProvinsi.setAdapter(provinceAdapter) binding.autoCompleteKabupaten.setAdapter(cityAdapter) + binding.autoCompleteKecamatan.setAdapter(subdistrictAdapter) + binding.autoCompleteDesa.setAdapter(villageAdapter) // Make dropdown appear on click (not just when typing) binding.autoCompleteProvinsi.setOnClickListener { @@ -131,6 +138,26 @@ class AddAddressActivity : AppCompatActivity() { } } + binding.autoCompleteKecamatan.setOnClickListener{ + if (subdistrictAdapter.count > 0){ + Log.d(TAG, "Subdistrict clicked, dropdown with ${subdistrictAdapter.count} items") + binding.autoCompleteKecamatan.showDropDown() + } else { + Log.d(TAG, "No kecamatan available") + Toast.makeText(this, "Pilih Kabupaten / Kota terlebih dahulu", Toast.LENGTH_SHORT).show() + } + } + + binding.autoCompleteDesa.setOnClickListener{ + if (villageAdapter.count > 0){ + Log.d(TAG, "Village clicked, dropdown with ${villageAdapter.count} items") + binding.autoCompleteDesa.showDropDown() + } else { + Log.d(TAG, "No desa available") + Toast.makeText(this, "Pilih Kecamatan terlebih dahulu", Toast.LENGTH_SHORT).show() + } + } + // Set listeners for selection binding.autoCompleteProvinsi.setOnItemClickListener { _, _, position, _ -> val provinceId = provinceAdapter.getProvinceId(position) @@ -149,9 +176,41 @@ class AddAddressActivity : AppCompatActivity() { cityId?.let { id -> Log.d(TAG, "Setting selectedCityId=$id") + viewModel.getSubdistrict(cityId) viewModel.selectedCityId = id + binding.autoCompleteKecamatan.text.clear() + } ?: Log.e(TAG, "Could not get cityId for position $position") } + + binding.autoCompleteKecamatan.setOnItemClickListener { _, _, position, _ -> + val subdistrictId = subdistrictAdapter.getSubdistrictId(position) + val subdistrictName = subdistrictAdapter.getSubdistrictName(position) + + Log.d(TAG, "Subdistrict selected at position $position, subsId=$subdistrictId") + + subdistrictId?.let { id -> + Log.d(TAG, "Setting subdistrict id=$id") + viewModel.getVillages(subdistrictId) + viewModel.selectedSubdistrictId = id + binding.autoCompleteDesa.text.clear() + } ?: Log.e(TAG, "Could not get subsId for position $position") + + subdistrictName?.let { name -> + Log.d(TAG, "Setting subdistrict=$name") + viewModel.selectedSubdistrict = name + } ?: Log.e(TAG, "COuldnt get subs name for position ${position}") + } + + binding.autoCompleteDesa.setOnItemClickListener { _, _, position, _ -> + val villageId = villageAdapter.getVillageId(position) + Log.d(TAG, "Village selected at position $position, villageId=$villageId") + + villageId?.let { id -> + Log.d(TAG, "Setting village=$id") + viewModel.selectedVillages = id + } ?: Log.e(TAG, "Could not get villageId for position $position") + } } private fun setupButtonListeners() { @@ -175,6 +234,16 @@ class AddAddressActivity : AppCompatActivity() { handleCityState(state) } + viewModel.subdistrictState.observe(this) {state -> + Log.d(TAG, "Received subdistrictId update: $state") + handleSubdistrictState(state) + } + + viewModel.villagesState.observe(this) {state -> + Log.d(TAG, "Received subdistrictId update: $state") + handleVillageState(state) + } + // Observe address submission viewModel.addressSubmissionState.observe(this) { state -> Log.d(TAG, "Received addressSubmissionState update: $state") @@ -199,7 +268,7 @@ class AddAddressActivity : AppCompatActivity() { } is ViewState.Error -> { // Hide loading indicator - showError("Failed to load provinces: ${state.message}") +// showError("Failed to load provinces: ${state.message}") Log.e("AddAddressActivity", "Province error: ${state.message}") } } @@ -218,12 +287,50 @@ class AddAddressActivity : AppCompatActivity() { } is ViewState.Error -> { binding.cityProgressBar.visibility = View.GONE - showError("Failed to load cities: ${state.message}") +// showError("Failed to load cities: ${state.message}") Log.e("AddAddressActivity", "City error: ${state.message}") } } } + private fun handleSubdistrictState(state: com.alya.ecommerce_serang.data.repository.Result>) { + when (state) { + is Result.Loading -> { + Log.d(TAG, "Loading subdistrict...") + binding.subdistrictProgressBar.visibility = View.VISIBLE + } + is Result.Success -> { + Log.d(TAG, "Subdistrict loaded: ${state.data.size}") + binding.subdistrictProgressBar.visibility = View.GONE + subdistrictAdapter.updateData(state.data) + } + is Result.Error -> { + binding.subdistrictProgressBar.visibility = View.GONE +// showError("Failed to load subs: ${state.message}") + Log.e(TAG, "Subdistrict error: ${state}") + } + } + } + + private fun handleVillageState(state: Result>) { + when (state) { + is Result.Loading -> { + Log.d(TAG, "Loading villages...") + binding.villageProgressBar.visibility = View.VISIBLE + } + is Result.Success -> { + Log.d(TAG, "Villages loaded: ${state.data.size}") + binding.villageProgressBar.visibility = View.GONE + villageAdapter.updateData(state.data) + } + is Result.Error -> { + binding.villageProgressBar.visibility = View.GONE +// showError("Failed to load subs: ${state.message}") + Log.e(TAG, "Village error: ${state}") + } + } + } + private fun handleAddressSubmissionState(state: ViewState) { when (state) { is ViewState.Loading -> { @@ -273,7 +380,7 @@ class AddAddressActivity : AppCompatActivity() { } val street = binding.etDetailAlamat.text.toString().trim() - val subDistrict = binding.etKecamatan.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 phone = binding.etNomorHp.text.toString().trim() @@ -282,9 +389,11 @@ class AddAddressActivity : AppCompatActivity() { val provinceId = viewModel.selectedProvinceId val cityId = viewModel.selectedCityId.toString() + val subDistrict = viewModel.selectedSubdistrict.toString() + val villageId = viewModel.selectedVillages.toString() 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, subdistrict=$subDistrict, villageId=$villageId " + "lat=$latitude, long=$longitude") // Validate required fields @@ -333,7 +442,7 @@ class AddAddressActivity : AppCompatActivity() { cityId = cityId, // ⚠️ Make sure this is Int provId = provinceId, postCode = postalCode, - idVillage = "", // Or provide a real ID if needed + idVillage = villageId, // Or provide a real ID if needed detailAddress = street, isStoreLocation = false, recipient = recipient, @@ -381,8 +490,8 @@ class AddAddressActivity : AppCompatActivity() { binding.locationProgressBar.visibility = View.GONE binding.tvLocationStatus.text = "Provider lokasi tidak tersedia" isRequestingLocation = false - Toast.makeText(this, "Provider lokasi tidak tersedia", Toast.LENGTH_SHORT).show() - showEnableLocationDialog() +// Toast.makeText(this, "Provider lokasi tidak tersedia", Toast.LENGTH_SHORT).show() +// showEnableLocationDialog() return } @@ -409,7 +518,7 @@ class AddAddressActivity : AppCompatActivity() { latitude = -6.200000 longitude = 106.816666 isRequestingLocation = false - Toast.makeText(this, "Timeout lokasi, menggunakan lokasi default", Toast.LENGTH_SHORT).show() +// Toast.makeText(this, "Timeout lokasi, menggunakan lokasi default", Toast.LENGTH_SHORT).show() } }, 60000) // 15 seconds timeout @@ -423,7 +532,7 @@ class AddAddressActivity : AppCompatActivity() { binding.locationProgressBar.visibility = View.GONE binding.tvLocationStatus.text = "Lokasi terdeteksi: ${lastLocation.latitude}, ${lastLocation.longitude}" isRequestingLocation = false - Toast.makeText(this, "Lokasi terdeteksi", Toast.LENGTH_SHORT).show() +// Toast.makeText(this, "Lokasi terdeteksi", Toast.LENGTH_SHORT).show() return } else { Log.d(TAG, "No last known location, requesting updates") @@ -441,7 +550,7 @@ class AddAddressActivity : AppCompatActivity() { binding.locationProgressBar.visibility = View.GONE binding.tvLocationStatus.text = "Lokasi terdeteksi: ${location.latitude}, ${location.longitude}" isRequestingLocation = false - Toast.makeText(this@AddAddressActivity, "Lokasi terdeteksi", Toast.LENGTH_SHORT).show() +// Toast.makeText(this@AddAddressActivity, "Lokasi terdeteksi", Toast.LENGTH_SHORT).show() // Remove location updates after receiving a location try { @@ -464,7 +573,7 @@ class AddAddressActivity : AppCompatActivity() { binding.locationProgressBar.visibility = View.GONE binding.tvLocationStatus.text = "Provider lokasi dimatikan" isRequestingLocation = false - Toast.makeText(this@AddAddressActivity, "Provider $provider dimatikan", Toast.LENGTH_SHORT).show() +// Toast.makeText(this@AddAddressActivity, "Provider $provider dimatikan", Toast.LENGTH_SHORT).show() } } @@ -483,7 +592,7 @@ class AddAddressActivity : AppCompatActivity() { binding.locationProgressBar.visibility = View.GONE binding.tvLocationStatus.text = "Error: ${e.message}" isRequestingLocation = false - Toast.makeText(this, "Error mendapatkan lokasi: ${e.message}", Toast.LENGTH_SHORT).show() +// Toast.makeText(this, "Error mendapatkan lokasi: ${e.message}", Toast.LENGTH_SHORT).show() // Set default location latitude = -6.200000 @@ -511,7 +620,7 @@ class AddAddressActivity : AppCompatActivity() { // Add button to reload location (add this button to your layout) binding.btnReloadLocation.setOnClickListener { Log.d(TAG, "Reload location button clicked") - Toast.makeText(this, "Memuat ulang lokasi...", Toast.LENGTH_SHORT).show() +// Toast.makeText(this, "Memuat ulang lokasi...", Toast.LENGTH_SHORT).show() requestLocation() } } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressViewModel.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressViewModel.kt index d7790a1..03af39d 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressViewModel.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/AddAddressViewModel.kt @@ -56,6 +56,7 @@ class AddAddressViewModel(private val repository: OrderRepository, private val u set(value) { savedStateHandle["selectedCityId"] = value } var selectedSubdistrict: String? = null + var selectedSubdistrictId: String? = null var selectedVillages: String? = null init { @@ -104,8 +105,6 @@ class AddAddressViewModel(private val repository: OrderRepository, private val u } } - - fun getProvinces() { _provincesState.value = ViewState.Loading viewModelScope.launch { @@ -150,18 +149,18 @@ class AddAddressViewModel(private val repository: OrderRepository, private val u viewModelScope.launch { try { - selectedSubdistrict = cityId + selectedSubdistrictId = cityId val result = repository.getListSubdistrict(cityId) result?.let { _subdistrictState.postValue(Result.Success(it.subdistricts)) - Log.d(TAG, "Cities loaded for province $cityId: ${it.subdistricts.size}") + Log.d(TAG, "Subdistrict loaded for city $cityId: ${it.subdistricts.size}") } ?: run { _subdistrictState.postValue(Result.Error(Exception("Failed to load cities"))) - Log.e(TAG, "City result was null for province $cityId") + Log.e(TAG, "Subdistrict result was null for city $cityId") } } catch (e: Exception) { _subdistrictState.postValue(Result.Error(Exception(e.message ?: "Error loading cities"))) - Log.e(TAG, "Error fetching cities for province $cityId", e) + Log.e(TAG, "Error fetching subdistrict for city $cityId", e) } } } @@ -175,14 +174,14 @@ class AddAddressViewModel(private val repository: OrderRepository, private val u val result = repository.getListVillages(subdistrictId) result?.let { _villagesState.postValue(Result.Success(it.villages)) - Log.d(TAG, "Cities loaded for province $subdistrictId: ${it.villages.size}") + Log.d(TAG, "Villages loaded for subdistrict $subdistrictId: ${it.villages.size}") } ?: run { _villagesState.postValue(Result.Error(Exception("Failed to load cities"))) - Log.e(TAG, "City result was null for province $subdistrictId") + Log.e(TAG, "Village result was null for subdistrict $subdistrictId") } } catch (e: Exception) { _villagesState.postValue(Result.Error(Exception(e.message ?: "Error loading cities"))) - Log.e(TAG, "Error fetching cities for province $subdistrictId", e) + Log.e(TAG, "Error fetching villages for subdistrict $subdistrictId", e) } } } @@ -248,6 +247,12 @@ class AddAddressViewModel(private val repository: OrderRepository, private val u addIfChanged("latitude", oldAddress.latitude, newAddress.latitude) addIfChanged("longitude", oldAddress.longitude, newAddress.longitude) addIfChanged("is_store_location", oldAddress.isStoreLocation, newAddress.isStoreLocation) + addIfChanged("village_name", oldAddress.villageName, newAddress.villageName) + addIfChanged("subdsitrict_id", oldAddress.subdistrictId, newAddress.subdistrictId) + addIfChanged("id", oldAddress.id, newAddress.id) + addIfChanged("user_id", oldAddress.userId, newAddress.userId) + addIfChanged("city_name", oldAddress.cityName, newAddress.cityName) + addIfChanged("province_name", oldAddress.provinceName, newAddress.provinceName) return params } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/EditAddressActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/EditAddressActivity.kt index 5724703..2cefa85 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/EditAddressActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/EditAddressActivity.kt @@ -371,19 +371,35 @@ class EditAddressActivity : AppCompatActivity() { private fun createNewAddressFromInputs(oldAddress: AddressDetail): AddressDetail { val selectedProvinceId = getSelectedProvinceId() val selectedCityId = getSelectedCityId() - val selectedSubdistrictId = getSelectedSubdistrictId() + val selectedSubdistrictName = getSelectedSubdistrictName() val selectedVillageId = getSelectedVillageId() + val selectedSubdistrictId = getSelectedSubdistrictId() + val selectedVillageName = getSelectedVillageName() + val selectedProvinceName = getSelectedProvinceName() - return oldAddress.copy( + Log.d(TAG, "Old subdistrict: ${oldAddress.subdistrict}") + Log.d(TAG, "Selected subdistrictId: $selectedSubdistrictName") + + val newAddress = oldAddress.copy( recipient = binding.etNamaPenerima.text.toString().trim(), phone = binding.etNomorHp.text.toString().trim(), detail = binding.etDetailAlamat.text.toString().trim(), postalCode = binding.etKodePos.text.toString().trim(), - provinceId = selectedProvinceId.toString(), - cityId = selectedCityId.toString(), - subdistrict = selectedSubdistrictId.toString(), - villageId = selectedVillageId + provinceId = selectedProvinceId?.toString() ?: oldAddress.provinceId, + cityId = selectedCityId ?: oldAddress.cityId, + subdistrict = selectedSubdistrictName ?: oldAddress.subdistrict, + villageId = selectedVillageId, + subdistrictId = selectedSubdistrictId ?: oldAddress.subdistrictId, + villageName = selectedVillageName ?: oldAddress.villageName, + provinceName = selectedProvinceName ?: oldAddress.provinceName ) + + // 🔎 Debug logs + Log.d(TAG, "New subdistrict: ${newAddress.subdistrict}") + Log.d(TAG, "New village name: ${newAddress.villageName}") + + + return newAddress } private fun getSelectedProvinceId(): Int? { @@ -392,12 +408,30 @@ class EditAddressActivity : AppCompatActivity() { return if (position >= 0) provinceAdapter.getProvinceId(position) else null } + private fun getSelectedProvinceName(): String? { + val selectedText = binding.autoCompleteProvinsi.text.toString() + val position = provincesList.indexOfFirst { it.province == selectedText } + return if (position >= 0) provinceAdapter.getProvinceName(position) else null + } + private fun getSelectedCityId(): String? { val selectedText = binding.autoCompleteKabupaten.text.toString() val position = citiesList.indexOfFirst { it.cityName == selectedText } return if (position >= 0) cityAdapter.getCityId(position) else null } + private fun getSelectedCityName(): String? { + val selectedText = binding.autoCompleteKabupaten.text.toString() + val position = citiesList.indexOfFirst { it.cityName == selectedText } + return if (position >= 0) cityAdapter.getCityName(position) else null + } + + private fun getSelectedSubdistrictName(): String? { + val selectedText = binding.autoCompleteKecamatan.text.toString() + val position = subdistrictsList.indexOfFirst { it.subdistrictName == selectedText } + return if (position >= 0) subdistrictAdapter.getSubdistrictName(position) else null + } + private fun getSelectedSubdistrictId(): String? { val selectedText = binding.autoCompleteKecamatan.text.toString() val position = subdistrictsList.indexOfFirst { it.subdistrictName == selectedText } @@ -410,6 +444,12 @@ class EditAddressActivity : AppCompatActivity() { return if (position >= 0) villageAdapter.getVillageId(position) else null } + private fun getSelectedVillageName(): String? { + val selectedText = binding.autoCompleteDesa.text.toString() + val position = villagesList.indexOfFirst { it.villageName == selectedText } + return if (position >= 0) villageAdapter.getVillageName(position) else null + } + companion object { const val EXTRA_ADDRESS_ID = "extra_address_id" private const val TAG = "EditAddressActivity" diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/ProvinceAdapter.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/ProvinceAdapter.kt index 82728e5..727ccb3 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/ProvinceAdapter.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/address/ProvinceAdapter.kt @@ -32,6 +32,10 @@ class ProvinceAdapter( fun getProvinceId(position: Int): Int? { return provinces.getOrNull(position)?.provinceId?.toIntOrNull() } + + fun getProvinceName(position: Int): String? { + return provinces.getOrNull(position)?.province?.toString() + } } class CityAdapter( @@ -53,6 +57,10 @@ class CityAdapter( fun getCityId(position: Int): String? { return cities.getOrNull(position)?.cityId?.toString() } + + fun getCityName(position: Int): String? { + return cities.getOrNull(position)?.cityName?.toString() + } } class SubdsitrictAdapter( @@ -99,6 +107,10 @@ class VillagesAdapter( fun getVillageId(position: Int): String? { return villages.getOrNull(position)?.villageId?.toString() } + + fun getVillageName(position: Int): String? { + return villages.getOrNull(position)?.villageName.toString() + } fun getPostalCode(position: Int): String?{ return villages.getOrNull(position)?.postalCode } diff --git a/app/src/main/res/layout/activity_add_address.xml b/app/src/main/res/layout/activity_add_address.xml index 986d62d..31bb2a1 100644 --- a/app/src/main/res/layout/activity_add_address.xml +++ b/app/src/main/res/layout/activity_add_address.xml @@ -168,25 +168,66 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" - android:text="Kecamatan / Desa" + android:text="Kecamatan" android:textColor="@android:color/black" android:textSize="14sp" /> - + + - + android:textSize="14sp" /> + + + + + + + + + + Date: Fri, 22 Aug 2025 01:08:25 +0700 Subject: [PATCH 4/4] fix fcm and update toast --- app/build.gradle.kts | 3 ++ .../ecommerce_serang/ui/auth/LoginActivity.kt | 6 +-- .../ui/auth/OtpBottomsheetDialog.kt | 2 +- .../ui/auth/RegisterActivity.kt | 1 - .../ui/auth/ResetPassActivity.kt | 2 +- .../auth/fragments/RegisterStep1Fragment.kt | 16 ++++--- .../auth/fragments/RegisterStep2Fragment.kt | 45 ++++++++++++++++--- .../auth/fragments/RegisterStep3Fragment.kt | 14 +++++- .../ecommerce_serang/ui/cart/CartActivity.kt | 11 +++-- .../ecommerce_serang/ui/chat/ChatActivity.kt | 6 +-- .../ui/chat/ChatListFragment.kt | 7 +-- .../ui/notif/fcm/FCMService.kt | 2 +- .../ui/order/CheckoutActivity.kt | 10 +++-- .../ui/order/ShippingActivity.kt | 2 +- .../detail/AddEvidencePaymentActivity.kt | 5 +-- .../ui/order/detail/PaymentActivity.kt | 3 +- .../ui/order/history/OrderHistoryAdapter.kt | 6 +-- .../cancelorder/CancelOrderBottomSheet.kt | 2 +- .../ui/order/review/CreateReviewActivity.kt | 4 +- .../ui/profile/DetailProfileActivity.kt | 3 +- .../ui/profile/ProfileFragment.kt | 32 +++++++++++-- .../profile/mystore/RegisterStoreActivity.kt | 2 +- .../utils/viewmodel/RegisterViewModel.kt | 30 +++++++++++++ app/src/main/res/layout/activity_checkout.xml | 9 ++++ .../res/layout/fragment_register_step2.xml | 18 ++++++-- .../res/layout/fragment_register_step3.xml | 20 ++++----- 26 files changed, 196 insertions(+), 65 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c34c44b..4fdc7b6 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -124,4 +124,7 @@ dependencies { implementation(platform("com.google.firebase:firebase-bom:33.13.0")) implementation("com.google.firebase:firebase-analytics") implementation("com.google.firebase:firebase-messaging-ktx") + + //Splash screen + implementation("androidx.core:core-splashscreen:1.0.0") } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/auth/LoginActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/LoginActivity.kt index 9d8184c..6013739 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/auth/LoginActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/LoginActivity.kt @@ -72,7 +72,7 @@ class LoginActivity : AppCompatActivity() { val password = binding.etLoginPassword.text.toString() if (email.isEmpty() || password.isEmpty()) { - Toast.makeText(this, "Please fill in all fields", Toast.LENGTH_SHORT).show() + Toast.makeText(this, "Mohon masukkan email atau password dengan benar", Toast.LENGTH_SHORT).show() } else { loginViewModel.login(email, password) } @@ -100,14 +100,14 @@ class LoginActivity : AppCompatActivity() { retrieveFCMToken() // sessionManager.saveUserId(response.userId) - Toast.makeText(this, "Login Successful", Toast.LENGTH_SHORT).show() + Toast.makeText(this, "Berhasil masuk", Toast.LENGTH_SHORT).show() startActivity(Intent(this, MainActivity::class.java)) finish() } 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, "Gagal masuk", Toast.LENGTH_LONG).show() } is Result.Loading -> { // Show loading state diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/auth/OtpBottomsheetDialog.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/OtpBottomsheetDialog.kt index c20b7f9..2bc3b4b 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/auth/OtpBottomsheetDialog.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/OtpBottomsheetDialog.kt @@ -29,7 +29,7 @@ class OtpBottomSheetDialog( onRegister(updatedUserData) // Send full data to ViewModel dismiss() // Close dialog } else { - Toast.makeText(requireContext(), "Please enter OTP", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), "Silahkan masukkan kode OTP", Toast.LENGTH_SHORT).show() } } return view diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/auth/RegisterActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/RegisterActivity.kt index 8a2c0a8..d040cf7 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/auth/RegisterActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/RegisterActivity.kt @@ -86,7 +86,6 @@ class RegisterActivity : AppCompatActivity() { } } - // navigate step register in fragment fun navigateToStep(step: Int, userData: RegisterRequest?) { val fragment = when (step) { 1 -> RegisterStep1Fragment.newInstance() diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/auth/ResetPassActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/ResetPassActivity.kt index 70cc88d..81bd108 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/auth/ResetPassActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/ResetPassActivity.kt @@ -111,7 +111,7 @@ class ResetPassActivity : AppCompatActivity() { } private fun handleError(errorMessage: String) { - Toast.makeText(this, "Error: $errorMessage", Toast.LENGTH_LONG).show() + Log.e(TAG, "Error: $errorMessage") // Optionally show error dialog AlertDialog.Builder(this) diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/auth/fragments/RegisterStep1Fragment.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/fragments/RegisterStep1Fragment.kt index 814a366..944c8f2 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/auth/fragments/RegisterStep1Fragment.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/fragments/RegisterStep1Fragment.kt @@ -155,19 +155,20 @@ class RegisterStep1Fragment : Fragment() { "email" -> { isEmailValid = isValid if (!isValid) { - Toast.makeText(requireContext(), "Email is already registered", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), "Email sudah digunakan. Gunakan email lainnya.", Toast.LENGTH_SHORT).show() } } "phone" -> { isPhoneValid = isValid if (!isValid) { - Toast.makeText(requireContext(), "Phone number is already registered", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), "Nomor handphone sudah digunakan. Gunakan nomor lainnya. ", Toast.LENGTH_SHORT).show() } } } } is com.alya.ecommerce_serang.data.repository.Result.Error -> { - Toast.makeText(requireContext(), "Validation failed: ${result.exception.message}", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), "Gagal melakukan validasi", Toast.LENGTH_SHORT).show() + Log.e(TAG, "Validation failed: ${result.exception.message}") } } } @@ -200,7 +201,8 @@ class RegisterStep1Fragment : Fragment() { is Result.Error -> { binding.progressBar.visibility = View.GONE binding.btnNext.isEnabled = true - Toast.makeText(requireContext(), "OTP Request Failed: ${result.exception.message}", Toast.LENGTH_SHORT).show() + Log.e(TAG, "OTP Request Failed: ${result.exception.message}") + Toast.makeText(requireContext(), "Gagal mendapatkan OTP. Kirim ulang OTP", Toast.LENGTH_SHORT).show() } } } @@ -229,13 +231,13 @@ class RegisterStep1Fragment : Fragment() { // Check if all fields are filled if (email.isEmpty() || password.isEmpty() || confirmPassword.isEmpty() || phone.isEmpty() || username.isEmpty() || fullName.isEmpty() || birthDate.isEmpty()) { - Toast.makeText(requireContext(), "Please fill all required fields", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), "Silahkan lengkapi seluruh isian", Toast.LENGTH_SHORT).show() return } // Check if passwords match if (password != confirmPassword) { - Toast.makeText(requireContext(), "Passwords do not match", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), "Konfirmasi kata sandi tidak sesua. Periksa kembali", Toast.LENGTH_SHORT).show() return } @@ -253,7 +255,7 @@ class RegisterStep1Fragment : Fragment() { if (isEmailValid && isPhoneValid) { requestOtp(email) } else { - Toast.makeText(requireContext(), "Please fix validation errors before proceeding", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), "Silahkan perbaiki data yang dimasukkan", Toast.LENGTH_SHORT).show() } } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/auth/fragments/RegisterStep2Fragment.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/fragments/RegisterStep2Fragment.kt index 15e3c22..0d60c7e 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/auth/fragments/RegisterStep2Fragment.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/fragments/RegisterStep2Fragment.kt @@ -1,5 +1,6 @@ package com.alya.ecommerce_serang.ui.auth.fragments +import android.content.Context import android.os.Build import android.os.Bundle import android.os.CountDownTimer @@ -13,6 +14,7 @@ import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import com.alya.ecommerce_serang.R +import com.alya.ecommerce_serang.data.api.dto.FcmReq import com.alya.ecommerce_serang.data.api.dto.RegisterRequest import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig import com.alya.ecommerce_serang.data.repository.OrderRepository @@ -24,6 +26,7 @@ import com.alya.ecommerce_serang.utils.BaseViewModelFactory import com.alya.ecommerce_serang.utils.SessionManager import com.alya.ecommerce_serang.utils.viewmodel.RegisterViewModel import com.google.android.material.progressindicator.LinearProgressIndicator +import com.google.firebase.messaging.FirebaseMessaging class RegisterStep2Fragment : Fragment() { private var _binding: FragmentRegisterStep2Binding? = null @@ -109,6 +112,10 @@ class RegisterStep2Fragment : Fragment() { } } + binding.btnBack.setOnClickListener { + parentFragmentManager.popBackStack() + } + observeRegistrationState() observeLoginState() Log.d(TAG, "Registration and login state observers set up") @@ -129,11 +136,6 @@ class RegisterStep2Fragment : Fragment() { Log.d(TAG, "Updating user data with OTP: $otp") registerViewModel.updateUserData(updatedUserData) - // For demo purposes, we're just proceeding to Step 3 - // In a real app, you would verify the OTP with the server first -// registerViewModel.setStep(3) -// (activity as? RegisterActivity)?.navigateToStep(3, updatedUserData) - registerViewModel.registerUser(updatedUserData) } ?: Log.e(TAG, "userData is null, cannot proceed with verification") } @@ -250,6 +252,8 @@ class RegisterStep2Fragment : Fragment() { // Save the token in fragment val accessToken = result.data.accessToken sessionManager.saveToken(accessToken) + retrieveFCMToken() + Log.d(TAG, "Token saved to SessionManager: $accessToken") // Proceed to Step 3 @@ -279,6 +283,37 @@ class RegisterStep2Fragment : Fragment() { } } + private fun retrieveFCMToken() { + FirebaseMessaging.getInstance().token + .addOnCompleteListener { task -> + if (!task.isSuccessful) { + Log.e(TAG, "Failed to get FCM token", task.exception) + return@addOnCompleteListener + } + + val token = task.result +// tokenTes = token + Log.d(TAG, "FCM token retrieved: $token") + + // Save token locally + val sharedPreferences = requireContext().getSharedPreferences("FCM_PREFS", Context.MODE_PRIVATE) + sharedPreferences.edit().putString("FCM_TOKEN", token).apply() + + // Send to your server + sendTokenToServer(token) + } + } + + private fun sendTokenToServer(token: String) { + Log.d(TAG, "Would send token to server: $token") + val tokenFcm=FcmReq( + fcmToken = token + ) + registerViewModel.sendFcm(tokenFcm) + Log.d(TAG, "Sent token fcm: $token") + + } + override fun onDestroyView() { super.onDestroyView() countDownTimer?.cancel() diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/auth/fragments/RegisterStep3Fragment.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/fragments/RegisterStep3Fragment.kt index 35585bc..d15acfb 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/auth/fragments/RegisterStep3Fragment.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/auth/fragments/RegisterStep3Fragment.kt @@ -104,11 +104,20 @@ class RegisterStep3Fragment : Fragment() { // Set up button listeners binding.btnPrevious.setOnClickListener { // Go back to the previous step - parentFragmentManager.popBackStack() +// parentFragmentManager.popBackStack() +// (activity as? RegisterActivity)?.navigateToStep(2, null) +// (activity as? RegisterActivity)?.goBackToPreviousStep() + + // Option 2: Direct navigation to step 1 + val step2Fragment = RegisterStep2Fragment() + parentFragmentManager.beginTransaction() + .replace(R.id.fragment_container, step2Fragment) + .commit() } binding.btnRegister.setOnClickListener { submitAddress() + sessionManager.clearAll() } // If user skips address entry @@ -503,7 +512,7 @@ class RegisterStep3Fragment : Fragment() { private fun showRegistrationSuccess() { // Now we can show the success message for the overall registration process - Toast.makeText(requireContext(), "Registration completed successfully!", Toast.LENGTH_LONG).show() + Toast.makeText(requireContext(), "Berhasil mendaftarkan akun", Toast.LENGTH_LONG).show() // Navigate to login screen startActivity(Intent(requireContext(), LoginActivity::class.java)) @@ -521,4 +530,5 @@ class RegisterStep3Fragment : Fragment() { ViewCompat.setWindowInsetsAnimationCallback(binding.root, null) _binding = null } + } \ No newline at end of file diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/cart/CartActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/cart/CartActivity.kt index 3df50c8..58b4951 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/cart/CartActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/cart/CartActivity.kt @@ -41,11 +41,16 @@ class CartActivity : AppCompatActivity() { } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + sessionManager = SessionManager(this) + apiService = ApiConfig.getApiService(sessionManager) + + binding = ActivityCartBinding.inflate(layoutInflater) setContentView(binding.root) - sessionManager = SessionManager(this) - apiService = ApiConfig.getApiService(sessionManager) + if (!sessionManager.isLoggedIn()){ + binding.emptyCart.text = "Silahkan masuk terlebih dahulu" + } WindowCompat.setDecorFitsSystemWindows(window, false) @@ -118,7 +123,7 @@ class CartActivity : AppCompatActivity() { // Start checkout with the prepared items startCheckoutWithWholesaleInfo(selectedItems) } else { - Toast.makeText(this, "Please select items from a single store only", Toast.LENGTH_SHORT).show() + Toast.makeText(this, "Pilih produk yang sama dengan toko", Toast.LENGTH_SHORT).show() } } } else { diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/chat/ChatActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/chat/ChatActivity.kt index cf9fa48..507dbea 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/chat/ChatActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/chat/ChatActivity.kt @@ -124,7 +124,7 @@ class ChatActivity : AppCompatActivity() { if (token.isEmpty()) { // User not logged in, redirect to login - Toast.makeText(this, "Please login first", Toast.LENGTH_SHORT).show() + Toast.makeText(this, "Silahkan masuk terlebih dahulu", Toast.LENGTH_SHORT).show() startActivity(Intent(this, LoginActivity::class.java)) finish() return @@ -506,7 +506,7 @@ class ChatActivity : AppCompatActivity() { } startActivity(intent) } catch (e: Exception) { - Toast.makeText(this, "Cannot open product details", Toast.LENGTH_SHORT).show() + Toast.makeText(this, "Gagal memuat produk", Toast.LENGTH_SHORT).show() Log.e(TAG, "Error navigating to product detail", e) } } @@ -622,7 +622,7 @@ class ChatActivity : AppCompatActivity() { if (outputFile.exists() && outputFile.length() > 0) { if (outputFile.length() > 5 * 1024 * 1024) { Log.e(TAG, "File too large: ${outputFile.length()} bytes") - Toast.makeText(this, "Image too large (max 5MB)", Toast.LENGTH_SHORT).show() + Toast.makeText(this, "Gambar terlalu besar. Maksimal 1MB", Toast.LENGTH_SHORT).show() return } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/chat/ChatListFragment.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/chat/ChatListFragment.kt index 923ad50..2abd8f4 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/chat/ChatListFragment.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/chat/ChatListFragment.kt @@ -5,7 +5,6 @@ import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.Toast import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig @@ -80,8 +79,10 @@ class ChatListFragment : Fragment() { } } is Result.Error -> { - binding.tvEmptyChat.visibility = View.VISIBLE - Toast.makeText(requireContext(), "Failed to load chats", Toast.LENGTH_SHORT).show() +// binding.tvEmptyChat.visibility = View.VISIBLE + binding.progressBarChat.visibility = View.VISIBLE +// Toast.makeText(requireContext(), "Failed to load chats", Toast.LENGTH_SHORT).show() + Log.e(TAG, "Failed to load chats") } Result.Loading -> { binding.progressBarChat.visibility = View.VISIBLE diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/notif/fcm/FCMService.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/notif/fcm/FCMService.kt index 0ae5b2e..e30b2d2 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/notif/fcm/FCMService.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/notif/fcm/FCMService.kt @@ -78,4 +78,4 @@ import com.google.firebase.messaging.RemoteMessage val notificationId = System.currentTimeMillis().toInt() notificationManager.notify(notificationId, notificationBuilder.build()) } - } \ No newline at end of file + } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/CheckoutActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/CheckoutActivity.kt index 127a1d6..1c23baf 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/CheckoutActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/CheckoutActivity.kt @@ -196,7 +196,7 @@ class CheckoutActivity : AppCompatActivity() { // Observe order creation viewModel.orderCreated.observe(this) { created -> if (created) { - Toast.makeText(this, "Order successfully created!", Toast.LENGTH_SHORT).show() + Toast.makeText(this, "Berhasil membuat pesanan", Toast.LENGTH_SHORT).show() setResult(RESULT_OK) finish() } @@ -206,10 +206,12 @@ class CheckoutActivity : AppCompatActivity() { private fun setupPaymentMethodsRecyclerView(paymentMethods: List) { if (paymentMethods.isEmpty()) { Log.e("CheckoutActivity", "Payment methods list is empty") - Toast.makeText(this, "No payment methods available", Toast.LENGTH_SHORT).show() + Toast.makeText(this, "Tidak ditemukan metode pembayaran", Toast.LENGTH_SHORT).show() + binding.tvEmptyPayment.visibility = View.VISIBLE return } + binding.tvEmptyPayment.visibility = View.GONE // Debug logging Log.d("CheckoutActivity", "Setting up payment methods: ${paymentMethods.size} methods available") @@ -313,7 +315,7 @@ class CheckoutActivity : AppCompatActivity() { binding.layoutShippingMethod.setOnClickListener { val addressId = viewModel.addressDetails.value?.id ?: 0 if (addressId <= 0) { - Toast.makeText(this, "Please select delivery address first", Toast.LENGTH_SHORT).show() + Toast.makeText(this, "Silahkan pilih metode pengiriman dahulu", Toast.LENGTH_SHORT).show() return@setOnClickListener } @@ -363,7 +365,7 @@ class CheckoutActivity : AppCompatActivity() { viewModel.setSelectedAddress(addressId) // You might want to show a toast or some UI feedback - Toast.makeText(this, "Address selected successfully", Toast.LENGTH_SHORT).show() + Toast.makeText(this, "Berhasil memilih alamat", Toast.LENGTH_SHORT).show() } } } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/ShippingActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/ShippingActivity.kt index 82bcde9..fb503ca 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/ShippingActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/ShippingActivity.kt @@ -67,7 +67,7 @@ class ShippingActivity : AppCompatActivity() { // Validate required information if (addressId <= 0 || productId <= 0) { Log.e(TAG, "Missing required shipping information: addressId=$addressId, productId=$productId") - Toast.makeText(this, "Missing required shipping information", Toast.LENGTH_SHORT).show() + Toast.makeText(this, "Gagal memuat pengiriman", Toast.LENGTH_SHORT).show() finish() return } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/detail/AddEvidencePaymentActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/detail/AddEvidencePaymentActivity.kt index 24a940a..806c878 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/detail/AddEvidencePaymentActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/detail/AddEvidencePaymentActivity.kt @@ -122,7 +122,6 @@ class AddEvidencePaymentActivity : AppCompatActivity() { } catch (e: Exception) { Log.e(TAG, "ERROR in AddEvidencePaymentActivity onCreate: ${e.message}", e) - Toast.makeText(this, "Error: ${e.message}", Toast.LENGTH_LONG).show() } } @@ -288,7 +287,7 @@ class AddEvidencePaymentActivity : AppCompatActivity() { } } catch (e: Exception) { Log.e(TAG, "Error handling selected image", e) - Toast.makeText(this, "Error: ${e.message}", Toast.LENGTH_SHORT).show() + Toast.makeText(this, "Terjadi kendala", Toast.LENGTH_SHORT).show() } } @@ -367,7 +366,7 @@ class AddEvidencePaymentActivity : AppCompatActivity() { viewModel.uploadPaymentProof(request) } catch (e: Exception) { Log.e(TAG, "Error creating upload request: ${e.message}", e) - Toast.makeText(this, "Error preparing upload: ${e.message}", Toast.LENGTH_SHORT).show() + Toast.makeText(this, "Gagal mengunggah foto", Toast.LENGTH_SHORT).show() } } } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/detail/PaymentActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/detail/PaymentActivity.kt index c470b52..6d7d8b5 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/detail/PaymentActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/detail/PaymentActivity.kt @@ -160,7 +160,8 @@ class PaymentActivity : AppCompatActivity() { viewModel.error.observe(this) { error -> if (error.isNotEmpty()) { - Toast.makeText(this, error, Toast.LENGTH_SHORT).show() + Toast.makeText(this, "Gagal melakukan pembayaran", Toast.LENGTH_SHORT).show() + Log.e(TAG, "Failed payment: $error") } } } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryAdapter.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryAdapter.kt index dad73a6..8db8d17 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryAdapter.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryAdapter.kt @@ -517,14 +517,14 @@ class OrderHistoryAdapter( } else { // Log error and show a Toast instead if we can't get a FragmentManager Log.e("OrderHistoryAdapter", "Cannot show bottom sheet: Context is not a FragmentActivity") - Toast.makeText(context, "Cannot show cancel order dialog", Toast.LENGTH_SHORT).show() + Toast.makeText(context, "Terjadi kendala", Toast.LENGTH_SHORT).show() return } } else -> { // Log error and show a Toast instead if we can't get a FragmentManager Log.e("OrderHistoryAdapter", "Cannot show bottom sheet: Context is not a FragmentActivity") - Toast.makeText(context, "Cannot show cancel order dialog", Toast.LENGTH_SHORT).show() + Toast.makeText(context, "Terjadi kendala", Toast.LENGTH_SHORT).show() return } } @@ -535,7 +535,7 @@ class OrderHistoryAdapter( onOrderCancelled = { callbacks.onOrderCancelled(orderId.toString(), true, "Order cancelled successfully") // Show a success message - Toast.makeText(context, "Order cancelled successfully", Toast.LENGTH_SHORT).show() + Toast.makeText(context, "Pesanan berhasil dibatalkan", Toast.LENGTH_SHORT).show() } ) diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/cancelorder/CancelOrderBottomSheet.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/cancelorder/CancelOrderBottomSheet.kt index 8fd0376..81be667 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/cancelorder/CancelOrderBottomSheet.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/cancelorder/CancelOrderBottomSheet.kt @@ -67,7 +67,7 @@ class CancelOrderBottomSheet( btnConfirm.setOnClickListener { if (selectedReason == null) { - Toast.makeText(context, "Please select a reason", Toast.LENGTH_SHORT).show() + Toast.makeText(context, "Pilih alasan pembatalan", Toast.LENGTH_SHORT).show() return@setOnClickListener } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/review/CreateReviewActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/review/CreateReviewActivity.kt index 1fbbc93..02dd4fb 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/review/CreateReviewActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/review/CreateReviewActivity.kt @@ -90,7 +90,7 @@ class CreateReviewActivity : AppCompatActivity() { ) }) } catch (e: Exception) { - Toast.makeText(this, "Error loading review items", Toast.LENGTH_SHORT).show() + Toast.makeText(this, "Gagal memuat ulasan", Toast.LENGTH_SHORT).show() finish() } } else { @@ -110,7 +110,7 @@ class CreateReviewActivity : AppCompatActivity() { ) ) } else { - Toast.makeText(this, "No items to review", Toast.LENGTH_SHORT).show() + Toast.makeText(this, "Tidak ada produk untuk direview", Toast.LENGTH_SHORT).show() finish() } } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/DetailProfileActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/DetailProfileActivity.kt index 3a5f99e..42069e5 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/DetailProfileActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/DetailProfileActivity.kt @@ -106,7 +106,8 @@ class DetailProfileActivity : AppCompatActivity() { } editProfileLauncher.launch(intent) } ?: run { - Toast.makeText(this, "Profile data is not available", Toast.LENGTH_SHORT).show() + Toast.makeText(this, "Akun tidak ditemukan", Toast.LENGTH_SHORT).show() + Log.e("DetailProfileActivity", "Profile data is not available") } } } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/ProfileFragment.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/ProfileFragment.kt index 27cc049..b515046 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/ProfileFragment.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/ProfileFragment.kt @@ -20,10 +20,10 @@ import com.alya.ecommerce_serang.data.repository.MyStoreRepository import com.alya.ecommerce_serang.data.repository.UserRepository import com.alya.ecommerce_serang.databinding.FragmentProfileBinding import com.alya.ecommerce_serang.ui.auth.LoginActivity -import com.alya.ecommerce_serang.ui.profile.mystore.RegisterStoreActivity import com.alya.ecommerce_serang.ui.order.address.AddressActivity import com.alya.ecommerce_serang.ui.order.history.HistoryActivity import com.alya.ecommerce_serang.ui.profile.mystore.MyStoreActivity +import com.alya.ecommerce_serang.ui.profile.mystore.RegisterStoreActivity import com.alya.ecommerce_serang.ui.profile.mystore.StoreOnReviewActivity import com.alya.ecommerce_serang.ui.profile.mystore.StoreSuspendedActivity import com.alya.ecommerce_serang.utils.BaseViewModelFactory @@ -58,7 +58,6 @@ class ProfileFragment : Fragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - sessionManager = SessionManager(requireContext()) } override fun onCreateView( @@ -72,6 +71,30 @@ class ProfileFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + sessionManager = SessionManager(requireContext()) + + if (!sessionManager.isLoggedIn()) { + // Redirect to LoginActivity + binding.tvName.text = "Selamat Datang" + binding.tvUsername.text = "Silahkan masuk" + binding.btnDetailProfile.text = "Masuk" + binding.btnDetailProfile.setOnClickListener { + val intent = Intent(requireContext(), LoginActivity::class.java) + intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK + startActivity(intent) + + // ✅ Finish the host activity so user can’t go back + requireActivity().finish() + } + + binding.containerBukaToko.visibility = View.GONE + binding.cardPesanan.visibility = View.GONE + binding.tvPengaturanAkun.visibility = View.GONE + binding.containerSettings.visibility = View.GONE + binding.cardAbout.visibility = View.GONE + binding.cardLogout.visibility = View.GONE + } + observeUserProfile() observeStoreStatus() @@ -130,7 +153,8 @@ class ProfileFragment : Fragment() { user?.let { updateUI(it) } } viewModel.errorMessage.observe(viewLifecycleOwner) { errorMessage -> - Toast.makeText(requireContext(), errorMessage, Toast.LENGTH_SHORT).show() +// Toast.makeText(requireContext(), errorMessage, Toast.LENGTH_SHORT).show() + Log.e("Profile Fragment", "Failed to load profile: $errorMessage") } } @@ -186,6 +210,8 @@ class ProfileFragment : Fragment() { sessionManager.clearAll() val intent = Intent(requireContext(), LoginActivity::class.java) startActivity(intent) + requireActivity().finish() + } catch (e: Exception) { Toast.makeText( requireContext(), diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/RegisterStoreActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/RegisterStoreActivity.kt index ac257d9..354f710 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/RegisterStoreActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/RegisterStoreActivity.kt @@ -302,7 +302,7 @@ class RegisterStoreActivity : AppCompatActivity() { viewModel.errorMessage.observe(this) { errorMsg -> if (errorMsg.isNotEmpty()) { Log.e(TAG, "setupStoreTypesObserver: Error loading store types: $errorMsg") - Toast.makeText(this, "Error loading store types: $errorMsg", Toast.LENGTH_SHORT).show() +// Toast.makeText(this, "Error loading store types: $errorMsg", Toast.LENGTH_SHORT).show() } } diff --git a/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/RegisterViewModel.kt b/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/RegisterViewModel.kt index d112774..bba65e0 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/RegisterViewModel.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/RegisterViewModel.kt @@ -7,9 +7,11 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.alya.ecommerce_serang.data.api.dto.CreateAddressRequest +import com.alya.ecommerce_serang.data.api.dto.FcmReq import com.alya.ecommerce_serang.data.api.dto.RegisterRequest import com.alya.ecommerce_serang.data.api.dto.ResetPassReq import com.alya.ecommerce_serang.data.api.dto.VerifRegisReq +import com.alya.ecommerce_serang.data.api.response.auth.FcmTokenResponse import com.alya.ecommerce_serang.data.api.response.auth.LoginResponse import com.alya.ecommerce_serang.data.api.response.auth.OtpResponse import com.alya.ecommerce_serang.data.api.response.auth.RegisterResponse @@ -388,6 +390,34 @@ class RegisterViewModel(private val repository: UserRepository, private val orde } + fun sendFcm(token: FcmReq) { + viewModelScope.launch { + _otpState.value = Result.Loading // Indicating API call in progress + + try { + // Call the repository function to request OTP + val authenticatedApiService = getAuthenticatedApiService() + val authenticatedOrderRepo = UserRepository(authenticatedApiService) + val response: FcmTokenResponse = authenticatedOrderRepo.sendFcm(token) + + // Log and store success message + Log.d("LoginViewModel", "OTP Response: ${response.message}") + _message.value = response.message ?: "berhasil" // Store the message for UI feedback + + // Update state to indicate success + _otpState.value = Result.Success(Unit) + + } catch (exception: Exception) { + // Handle any errors and update state + _otpState.value = Result.Error(exception) + _message.value = exception.localizedMessage ?: "Failed to request OTP" + + // Log the error for debugging + Log.e("LoginViewModel", "OTP request failed for: $token", exception) + } + } + } + companion object { private const val TAG = "RegisterViewModel" } diff --git a/app/src/main/res/layout/activity_checkout.xml b/app/src/main/res/layout/activity_checkout.xml index 0e3b15c..10944b5 100644 --- a/app/src/main/res/layout/activity_checkout.xml +++ b/app/src/main/res/layout/activity_checkout.xml @@ -257,6 +257,15 @@ android:textSize="14sp" android:layout_marginBottom="8dp" /> + + @@ -61,9 +62,20 @@ android:id="@+id/btn_verify" android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="Verify" + android:text="Kirim kode OTP" + style="@style/button.large.active.medium" app:cornerRadius="8dp" /> + + diff --git a/app/src/main/res/layout/fragment_register_step3.xml b/app/src/main/res/layout/fragment_register_step3.xml index 779f947..7c78223 100644 --- a/app/src/main/res/layout/fragment_register_step3.xml +++ b/app/src/main/res/layout/fragment_register_step3.xml @@ -233,6 +233,12 @@ android:padding="12dp" android:textSize="14sp" /> + +