mirror of
https://github.com/shaulascr/ecommerce_serang.git
synced 2025-08-10 09:22:21 +00:00
fix bug
This commit is contained in:
1
app/.gitignore
vendored
1
app/.gitignore
vendored
@ -1 +1,2 @@
|
||||
/build
|
||||
google-services.json
|
@ -15,10 +15,14 @@ class ApiConfig {
|
||||
|
||||
val loggingInterceptor = HttpLoggingInterceptor().apply {
|
||||
level = HttpLoggingInterceptor.Level.BODY
|
||||
//httplogginginterceptor ntuk debug dan monitoring request/response
|
||||
}
|
||||
|
||||
val authInterceptor = AuthInterceptor(tokenManager)
|
||||
// utk tambak token auth otomatis pada header
|
||||
|
||||
// Konfigurasi OkHttpClient
|
||||
//Low-level HTTP client yang melakukan actual network request
|
||||
val client = OkHttpClient.Builder()
|
||||
.addInterceptor(loggingInterceptor)
|
||||
.addInterceptor(authInterceptor)
|
||||
@ -27,13 +31,17 @@ class ApiConfig {
|
||||
.writeTimeout(300, TimeUnit.SECONDS) // 5 minutes
|
||||
.build()
|
||||
|
||||
// Konfigurasi Retrofit
|
||||
val retrofit = Retrofit.Builder()
|
||||
//almat domain backend
|
||||
.baseUrl(BuildConfig.BASE_URL)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
//gson convertes: mengkonversi JSON ke object Kotlin dan sebaliknya
|
||||
.client(client)
|
||||
.build()
|
||||
|
||||
return retrofit.create(ApiService::class.java)
|
||||
// retrofit : menyederhanakan HTTP Request dgn mengubah interface Kotlin di ApiService menjadi HTTP calls secara otomatis
|
||||
}
|
||||
|
||||
fun getUnauthenticatedApiService(): ApiService {
|
||||
|
@ -8,9 +8,7 @@ import android.widget.Toast
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import com.alya.ecommerce_serang.data.api.dto.FcmReq
|
||||
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
|
||||
import com.alya.ecommerce_serang.data.repository.Result
|
||||
@ -43,20 +41,18 @@ class LoginActivity : AppCompatActivity() {
|
||||
setContentView(binding.root)
|
||||
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
|
||||
enableEdgeToEdge()
|
||||
|
||||
// Apply insets to your root layout
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
|
||||
val systemBars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
view.setPadding(
|
||||
systemBars.left,
|
||||
systemBars.top,
|
||||
systemBars.right,
|
||||
systemBars.bottom
|
||||
)
|
||||
windowInsets
|
||||
}
|
||||
// ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
|
||||
// val systemBars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
// view.setPadding(
|
||||
// systemBars.left,
|
||||
// systemBars.top,
|
||||
// systemBars.right,
|
||||
// systemBars.bottom
|
||||
// )
|
||||
// windowInsets
|
||||
// }
|
||||
|
||||
// onBackPressedDispatcher.addCallback(this) {
|
||||
// // Handle the back button event
|
||||
|
@ -43,24 +43,6 @@ class RegisterActivity : AppCompatActivity() {
|
||||
setContentView(binding.root)
|
||||
sessionManager = SessionManager(this)
|
||||
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
|
||||
enableEdgeToEdge()
|
||||
|
||||
// Apply insets to your root layout
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
|
||||
val systemBars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
view.setPadding(
|
||||
systemBars.left,
|
||||
systemBars.top,
|
||||
systemBars.right,
|
||||
systemBars.bottom
|
||||
)
|
||||
windowInsets
|
||||
}
|
||||
|
||||
|
||||
|
||||
Log.d("RegisterActivity", "Token in storage: '${sessionManager.getToken()}'")
|
||||
Log.d("RegisterActivity", "User ID in storage: '${sessionManager.getUserId()}'")
|
||||
|
||||
@ -104,7 +86,7 @@ class RegisterActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
// Function to navigate to the next fragment
|
||||
// navigate step register in fragment
|
||||
fun navigateToStep(step: Int, userData: RegisterRequest?) {
|
||||
val fragment = when (step) {
|
||||
1 -> RegisterStep1Fragment.newInstance()
|
||||
|
@ -204,6 +204,13 @@ class RegisterStep1Fragment : Fragment() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerViewModel.toastMessage.observe(viewLifecycleOwner){ event ->
|
||||
//memanggil toast check value email dan phone
|
||||
event.getContentIfNotHandled()?.let { msg ->
|
||||
Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun validateAndProceed() {
|
||||
|
@ -252,15 +252,10 @@ class RegisterStep2Fragment : Fragment() {
|
||||
sessionManager.saveToken(accessToken)
|
||||
Log.d(TAG, "Token saved to SessionManager: $accessToken")
|
||||
|
||||
// Also save user ID if available in the login response
|
||||
// result.data.?.let { userId ->
|
||||
// sessionManager.saveUserId(userId)
|
||||
// }
|
||||
|
||||
Log.d(TAG, "Login successful, token saved: $accessToken")
|
||||
|
||||
// Proceed to Step 3
|
||||
Log.d(TAG, "Proceeding to Step 3 after successful login")
|
||||
|
||||
// call navigate register step from activity
|
||||
(activity as? RegisterActivity)?.navigateToStep(3, null )
|
||||
}
|
||||
is Result.Error -> {
|
||||
@ -270,7 +265,7 @@ class RegisterStep2Fragment : Fragment() {
|
||||
|
||||
// Show error message but continue to Step 3 anyway
|
||||
Log.e(TAG, "Login failed but proceeding to Step 3", result.exception)
|
||||
Toast.makeText(requireContext(), "Gagal login, namun berhasil membuat akun", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(requireContext(), "Berhasil membuat akun, namun belum login", Toast.LENGTH_SHORT).show()
|
||||
|
||||
// Proceed to Step 3
|
||||
(activity as? RegisterActivity)?.navigateToStep(3, null)
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.alya.ecommerce_serang.ui.cart
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
@ -153,7 +154,8 @@ class CartActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
viewModel.isLoading.observe(this) { isLoading ->
|
||||
// Show/hide loading indicator if needed
|
||||
binding.progressBarCart?.visibility = if (isLoading) View.VISIBLE else View.GONE
|
||||
Log.d("CartActivity", "Loading state: $isLoading")
|
||||
}
|
||||
|
||||
viewModel.errorMessage.observe(this) { errorMessage ->
|
||||
|
@ -129,6 +129,7 @@ class ChatActivity : AppCompatActivity() {
|
||||
return
|
||||
}
|
||||
|
||||
// set up data toko
|
||||
binding.tvStoreName.text = storeName
|
||||
val fullImageUrl = when (val img = storeImg) {
|
||||
is String -> {
|
||||
@ -142,7 +143,7 @@ class ChatActivity : AppCompatActivity() {
|
||||
.placeholder(R.drawable.placeholder_image)
|
||||
.into(binding.imgProfile)
|
||||
|
||||
// Set chat parameters to ViewModel
|
||||
// Set chat parameter to send to ViewModel with product
|
||||
viewModel.setChatParameters(
|
||||
storeId = storeId,
|
||||
productId = productId,
|
||||
@ -159,10 +160,12 @@ class ChatActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
// Setup UI components
|
||||
// rv isi chat
|
||||
setupRecyclerView()
|
||||
setupWindowInsets()
|
||||
setupListeners()
|
||||
setupTypingIndicator()
|
||||
// observe listener from viewmodel
|
||||
observeViewModel()
|
||||
|
||||
// If opened from ChatListFragment with a valid chatRoomId
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.alya.ecommerce_serang.ui.chat
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@ -55,31 +56,44 @@ class ChatListFragment : Fragment() {
|
||||
viewModel.chatList.observe(viewLifecycleOwner) { result ->
|
||||
when (result) {
|
||||
is Result.Success -> {
|
||||
val adapter = ChatListAdapter(result.data) { chatItem ->
|
||||
// Use the ChatActivity.createIntent factory method for proper navigation
|
||||
ChatActivity.createIntent(
|
||||
context = requireActivity(),
|
||||
storeId = chatItem.storeId,
|
||||
productId = 0, // Default value since we don't have it in ChatListItem
|
||||
productName = null, // Null is acceptable as per ChatActivity
|
||||
productPrice = "",
|
||||
productImage = null,
|
||||
productRating = null,
|
||||
storeName = chatItem.storeName,
|
||||
chatRoomId = chatItem.chatRoomId,
|
||||
storeImage = chatItem.storeImage
|
||||
)
|
||||
val data = result.data
|
||||
|
||||
binding.tvEmptyChat.visibility = View.GONE
|
||||
if (data.isNotEmpty()) {
|
||||
val adapter = ChatListAdapter(data) { chatItem ->
|
||||
ChatActivity.createIntent(
|
||||
context = requireActivity(),
|
||||
storeId = chatItem.storeId,
|
||||
productId = 0,
|
||||
productName = null,
|
||||
productPrice = "",
|
||||
productImage = null,
|
||||
productRating = null,
|
||||
storeName = chatItem.storeName,
|
||||
chatRoomId = chatItem.chatRoomId,
|
||||
storeImage = chatItem.storeImage
|
||||
)
|
||||
}
|
||||
binding.chatListRecyclerView.adapter = adapter
|
||||
} else {
|
||||
binding.tvEmptyChat.visibility = View.VISIBLE
|
||||
}
|
||||
binding.chatListRecyclerView.adapter = adapter
|
||||
}
|
||||
is Result.Error -> {
|
||||
binding.tvEmptyChat.visibility = View.VISIBLE
|
||||
Toast.makeText(requireContext(), "Failed to load chats", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
Result.Loading -> {
|
||||
binding.progressBarChat.visibility = View.VISIBLE
|
||||
// Optional: show progress bar
|
||||
}
|
||||
}
|
||||
}
|
||||
//loading chat list
|
||||
viewModel.isLoading.observe(viewLifecycleOwner) { isLoading ->
|
||||
binding.progressBarChat?.visibility = if (isLoading) View.VISIBLE else View.GONE
|
||||
Log.d(TAG, "Loading state: $isLoading")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -89,6 +103,6 @@ class ChatListFragment : Fragment() {
|
||||
}
|
||||
|
||||
companion object{
|
||||
|
||||
private var TAG = "ChatListFragment"
|
||||
}
|
||||
}
|
@ -60,6 +60,9 @@ class ChatViewModel @Inject constructor(
|
||||
private val _state = MutableLiveData(ChatUiState())
|
||||
val state: LiveData<ChatUiState> = _state
|
||||
|
||||
private val _isLoading = MutableLiveData<Boolean>()
|
||||
val isLoading: LiveData<Boolean> = _isLoading
|
||||
|
||||
val _chatRoomId = MutableLiveData<Int>(0)
|
||||
val chatRoomId: LiveData<Int> = _chatRoomId
|
||||
|
||||
@ -94,12 +97,15 @@ class ChatViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
private fun initializeUser() {
|
||||
_isLoading.value = true
|
||||
viewModelScope.launch {
|
||||
Log.d(TAG, "Initializing user session...")
|
||||
|
||||
when (val result = chatRepository.fetchUserProfile()) {
|
||||
is Result.Success -> {
|
||||
currentUserId = result.data?.userId
|
||||
_isLoading.value = false
|
||||
|
||||
Log.d(TAG, "User session initialized - User ID: $currentUserId")
|
||||
|
||||
if (currentUserId == null || currentUserId == 0) {
|
||||
@ -111,10 +117,12 @@ class ChatViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
is Result.Error -> {
|
||||
_isLoading.value = false
|
||||
Log.e(TAG, "Failed to fetch user profile: ${result.exception.message}")
|
||||
updateState { it.copy(error = "User authentication error. Please login again.") }
|
||||
}
|
||||
is Result.Loading -> {
|
||||
_isLoading.value = true
|
||||
Log.d(TAG, "Loading user profile...")
|
||||
}
|
||||
}
|
||||
@ -335,10 +343,13 @@ class ChatViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
fun getChatList() {
|
||||
_isLoading.value = true
|
||||
Log.d(TAG, "Getting chat list...")
|
||||
viewModelScope.launch {
|
||||
_chatList.value = Result.Loading
|
||||
// _chatList.value = Result.Loading
|
||||
_chatList.value = chatRepository.getListChat()
|
||||
_isLoading.value = false
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,25 +208,6 @@ class HomeFragment : Fragment() {
|
||||
private fun initUi() {
|
||||
// For LightStatusBar
|
||||
setLightStatusBar()
|
||||
// val banners = binding.banners
|
||||
// banners.offscreenPageLimit = 1
|
||||
//
|
||||
// val nextItemVisiblePx = resources.getDimension(R.dimen.viewpager_next_item_visible)
|
||||
// val currentItemHorizontalMarginPx =
|
||||
// resources.getDimension(R.dimen.viewpager_current_item_horizontal_margin)
|
||||
// val pageTranslationX = nextItemVisiblePx + currentItemHorizontalMarginPx
|
||||
//
|
||||
// banners.setPageTransformer { page, position ->
|
||||
// page.translationX = -pageTranslationX * position
|
||||
// page.scaleY = 1 - (0.25f * kotlin.math.abs(position))
|
||||
// }
|
||||
//
|
||||
// banners.addItemDecoration(
|
||||
// HorizontalMarginItemDecoration(
|
||||
// requireContext(),
|
||||
// R.dimen.viewpager_current_item_horizontal_margin
|
||||
// )
|
||||
// )
|
||||
}
|
||||
|
||||
private fun handleProductClick(product: ProductsItem) {
|
||||
@ -248,8 +229,4 @@ class HomeFragment : Fragment() {
|
||||
categoryAdapter = null
|
||||
_binding = null
|
||||
}
|
||||
|
||||
// private fun showLoading(isLoading: Boolean) {
|
||||
// binding.progressBar.isVisible = isLoading
|
||||
// }
|
||||
}
|
@ -4,6 +4,7 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
@ -110,11 +111,6 @@ class CheckoutActivity : AppCompatActivity() {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
// viewModel.getPaymentMethods { paymentMethods ->
|
||||
// // Logging is just for debugging
|
||||
// Log.d("CheckoutActivity", "Loaded ${paymentMethods.size} payment methods")
|
||||
// }
|
||||
}
|
||||
|
||||
private fun setupToolbar() {
|
||||
@ -165,7 +161,7 @@ class CheckoutActivity : AppCompatActivity() {
|
||||
// Observe loading state
|
||||
viewModel.isLoading.observe(this) { isLoading ->
|
||||
binding.btnPay.isEnabled = !isLoading
|
||||
// Show/hide loading indicator if you have one
|
||||
|
||||
}
|
||||
|
||||
// Observe error messages
|
||||
@ -273,10 +269,14 @@ class CheckoutActivity : AppCompatActivity() {
|
||||
private fun updateShippingUI(shipName: String, shipService: String, shipEtd: String, shipPrice: Int) {
|
||||
if (shipName.isNotEmpty() && shipService.isNotEmpty()) {
|
||||
// Display shipping name and service in one line
|
||||
binding.cardShipment.visibility = View.VISIBLE
|
||||
|
||||
binding.tvCourierName.text = "$shipName $shipService"
|
||||
binding.tvDeliveryEstimate.text = "$shipEtd hari kerja"
|
||||
binding.tvShippingPrice.text = formatCurrency(shipPrice.toDouble())
|
||||
binding.rbJne.isChecked = true
|
||||
} else {
|
||||
binding.cardShipment.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,9 @@ import com.google.gson.Gson
|
||||
import java.io.File
|
||||
import java.text.NumberFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.time.Instant
|
||||
import java.time.ZoneId
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import java.util.TimeZone
|
||||
@ -197,12 +200,12 @@ class DetailOrderStatusActivity : AppCompatActivity() {
|
||||
Log.d(TAG, "populateOrderDetails: Payment method=${orders.payInfoName ?: "Tidak tersedia"}")
|
||||
|
||||
// Set subtotal, shipping cost, and total
|
||||
val subtotal = orders.totalAmount?.minus(orders.shipmentPrice.toIntOrNull() ?: 0) ?: 0
|
||||
binding.tvSubtotal.text = formatCurrency(subtotal.toDouble())
|
||||
// val subtotal = orders.totalAmount?.minus(orders.shipmentPrice.toDouble() ?: 0) ?: 0
|
||||
// binding.tvSubtotal.text = formatCurrency(subtotal.toDouble())
|
||||
binding.tvShippingCost.text = formatCurrency(orders.shipmentPrice.toDouble())
|
||||
binding.tvTotal.text = formatCurrency(orders.totalAmount?.toDouble() ?: 0.00)
|
||||
|
||||
Log.d(TAG, "populateOrderDetails: Subtotal=$subtotal, Shipping=${orders.shipmentPrice}, Total=${orders.totalAmount}")
|
||||
Log.d(TAG, "populateOrderDetails: Subtotal=, Shipping=${orders.shipmentPrice}, Total=${orders.totalAmount}")
|
||||
|
||||
// Adjust buttons based on order status
|
||||
Log.d(TAG, "populateOrderDetails: Adjusting buttons for status=$orderStatus")
|
||||
@ -223,6 +226,11 @@ class DetailOrderStatusActivity : AppCompatActivity() {
|
||||
this.adapter = adapter
|
||||
}
|
||||
adapter.submitList(orderItems)
|
||||
|
||||
// get data from ordetlistitemsitem untuk ambil subtotal nya dan dijumlahkan
|
||||
val subtotalSum = orderItems.sumOf { it.subtotal }
|
||||
binding.tvSubtotal.text = formatCurrency(subtotalSum.toDouble())
|
||||
|
||||
}
|
||||
|
||||
private fun adjustButtonsBasedOnStatus(orders: Orders, status: String) {
|
||||
@ -287,7 +295,7 @@ class DetailOrderStatusActivity : AppCompatActivity() {
|
||||
// Show status note
|
||||
binding.tvStatusHeader.text = "Sudah Dibayar"
|
||||
binding.tvStatusNote.visibility = View.VISIBLE
|
||||
binding.tvStatusNote.text = "Menunggu pesanan dikonfirmasi penjual ${formatDatePay(orders.updatedAt)}"
|
||||
binding.tvStatusNote.text = "Menunggu pesanan dikonfirmasi penjual ${formatDatePaid(orders.updatedAt)}"
|
||||
binding.tvPaymentDeadlineLabel.text = "Batas konfirmasi penjual:"
|
||||
binding.tvPaymentDeadline.text = formatDatePaid(orders.updatedAt)
|
||||
|
||||
@ -606,32 +614,17 @@ class DetailOrderStatusActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun formatDate(dateString: String): String {
|
||||
Log.d(TAG, "formatDate: Formatting date: $dateString")
|
||||
|
||||
return try {
|
||||
val inputFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault())
|
||||
inputFormat.timeZone = TimeZone.getTimeZone("UTC")
|
||||
val jakarta = ZoneId.of("Asia/Jakarta")
|
||||
val instant = Instant.parse(dateString) // parses ISO‑8601 with ‘Z’
|
||||
val zoned = instant.atZone(jakarta)
|
||||
|
||||
val timeFormat = SimpleDateFormat("HH:mm", Locale("id", "ID"))
|
||||
val dateFormat = SimpleDateFormat("dd MMMM yyyy", Locale("id", "ID"))
|
||||
val time = DateTimeFormatter.ofPattern("HH:mm", Locale("id", "ID")).format(zoned)
|
||||
val date = DateTimeFormatter.ofPattern("dd MMMM yyyy",Locale("id", "ID")).format(zoned)
|
||||
|
||||
val date = inputFormat.parse(dateString)
|
||||
|
||||
date?.let {
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.time = it
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 23)
|
||||
calendar.set(Calendar.MINUTE, 59)
|
||||
|
||||
val timePart = timeFormat.format(calendar.time)
|
||||
val datePart = dateFormat.format(calendar.time)
|
||||
|
||||
val formatted = "$timePart\n$datePart"
|
||||
Log.d(TAG, "formatDate: Formatted date: $formatted")
|
||||
formatted
|
||||
} ?: dateString
|
||||
"$time\n$date"
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "formatDate: Error formatting date: ${e.message}", e)
|
||||
Log.e(TAG, "formatDate: $e")
|
||||
dateString
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +64,9 @@ class RegisterViewModel(private val repository: UserRepository, private val orde
|
||||
private val _registeredUser = MutableLiveData<User>()
|
||||
val registeredUser: LiveData<User> = _registeredUser
|
||||
|
||||
private val _toastMessage = MutableLiveData<com.alya.ecommerce_serang.utils.viewmodel.Event<String>>()
|
||||
val toastMessage: LiveData<com.alya.ecommerce_serang.utils.viewmodel.Event<String>> = _toastMessage
|
||||
|
||||
// For address data
|
||||
var selectedProvinceId: Int? = null
|
||||
var selectedCityId: String? = null
|
||||
@ -224,9 +227,16 @@ class RegisterViewModel(private val repository: UserRepository, private val orde
|
||||
Log.d("RegisterViewModel", "OTP Response: ${response.available}")
|
||||
_checkValue.value = Result.Success(response.available)// Store the message for UI feedback
|
||||
|
||||
val msg = if (response.available)
|
||||
"${request.fieldRegis.capitalize()} dapat digunakan"
|
||||
else
|
||||
"${request.fieldRegis.capitalize()} sudah terdaftar"
|
||||
_toastMessage.value = Event(msg)
|
||||
|
||||
} catch (exception: Exception) {
|
||||
// Handle any errors and update state
|
||||
_checkValue.value = Result.Error(exception)
|
||||
_toastMessage.value = Event("Gagal memeriksa ${request.fieldRegis}")
|
||||
|
||||
// Log the error for debugging
|
||||
Log.e("RegisterViewModel", "Error:", exception)
|
||||
@ -375,4 +385,10 @@ class RegisterViewModel(private val repository: UserRepository, private val orde
|
||||
companion object {
|
||||
private const val TAG = "RegisterViewModel"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Event<out T>(private val data: T) {
|
||||
private var handled = false
|
||||
fun getContentIfNotHandled(): T? = if (handled) null else { handled = true; data }
|
||||
}
|
@ -21,6 +21,18 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/header"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBarCart"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toTopOf="@+id/bottomCheckoutLayout"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/header"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvWholesaleWarning"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -6,7 +6,7 @@
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/black_800"
|
||||
android:background="@color/white"
|
||||
android:theme="@style/Theme.Ecommerce_serang"
|
||||
tools:context=".ui.order.CheckoutActivity">
|
||||
|
||||
@ -75,7 +75,7 @@
|
||||
android:id="@+id/tv_places_address"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Rumah"
|
||||
android:text="-"
|
||||
android:textColor="#5A5A5A"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:paddingVertical="2dp"
|
||||
@ -94,7 +94,7 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Jl. Pegangasan Timur"
|
||||
android:text="-"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginStart="32dp" />
|
||||
|
||||
@ -179,9 +179,11 @@
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_shipment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:visibility="gone"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="0dp"
|
||||
app:cardBackgroundColor="#F5F5F5">
|
||||
|
@ -3,38 +3,48 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:theme="@style/Theme.Ecommerce_serang"
|
||||
tools:context=".ui.product.listproduct.ListProductActivity">
|
||||
|
||||
<include
|
||||
android:id="@+id/searchContainerList"
|
||||
layout="@layout/view_search_back"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/rvProductsList"/>
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
<include
|
||||
android:id="@+id/searchContainerList"
|
||||
layout="@layout/view_search_back"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"/>
|
||||
|
||||
<!-- <com.google.android.material.divider.MaterialDivider-->
|
||||
<!-- android:id="@+id/divider_product"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_marginTop="2dp"-->
|
||||
<!-- app:layout_constraintTop_toBottomOf="@id/searchContainer"/>-->
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvProductsList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="23dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/searchContainerList"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginTop="4dp"
|
||||
app:spanCount="2"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
tools:listitem="@layout/item_product_grid"
|
||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- <com.google.android.material.divider.MaterialDivider-->
|
||||
<!-- android:id="@+id/divider_product"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_marginTop="2dp"-->
|
||||
<!-- app:layout_constraintTop_toBottomOf="@id/searchContainer"/>-->
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvProductsList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="23dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/searchContainerList"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginTop="4dp"
|
||||
app:spanCount="2"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
tools:listitem="@layout/item_product_grid"
|
||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -1,97 +1,136 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginVertical="16dp"
|
||||
android:paddingHorizontal="32dp"
|
||||
android:paddingVertical="16dp"
|
||||
tools:context=".ui.auth.LoginActivity">
|
||||
|
||||
<!-- Title -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/tv_login_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/login"
|
||||
android:textAlignment="center"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:textAlignment="center"
|
||||
android:layout_marginBottom="24dp"/>
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@+id/tv_email_label"
|
||||
android:layout_marginBottom="48dp"
|
||||
android:paddingBottom="24dp"/>
|
||||
|
||||
<!-- Email label -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/tv_email_label"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:fontFamily="@font/dmsans_medium"
|
||||
android:text="@string/login_email"
|
||||
android:textSize="18sp"
|
||||
android:text="@string/login_email"/>
|
||||
android:layout_marginVertical="8dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_login_title"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<!-- Email input -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/til_login_email"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_email_label"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/et_login_email"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/hint_login_email"
|
||||
android:inputType="textEmailAddress"/>
|
||||
android:inputType="textEmailAddress" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!-- Password label-->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/tv_password_label"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:fontFamily="@font/dmsans_medium"
|
||||
android:text="@string/password"
|
||||
android:textSize="18sp"
|
||||
android:text="@string/password"/>
|
||||
android:layout_marginVertical="8dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/til_login_email"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<!-- Password input -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/til_login_password"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
app:passwordToggleEnabled="true">
|
||||
app:passwordToggleEnabled="true"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_password_label"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/et_login_password"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/hint_login_password"
|
||||
android:inputType="textPassword"/>
|
||||
android:inputType="textPassword" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!-- “Forgot password” link -->
|
||||
<TextView
|
||||
android:id="@+id/tv_forgetPassword"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/forget_password"
|
||||
android:textColor="@android:color/holo_red_light"
|
||||
android:textAlignment="textEnd"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
android:textColor="@android:color/holo_red_light"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/til_login_password" />
|
||||
|
||||
<!-- Login button -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_login"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/login"
|
||||
app:cornerRadius="8dp"/>
|
||||
app:cornerRadius="8dp"
|
||||
android:layout_marginVertical="16dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_forgetPassword" />
|
||||
|
||||
<!-- “Don’t have an account?” row (kept as LinearLayout) -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/ll_signup_row"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center"
|
||||
android:layout_marginTop="16dp">
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/btn_login">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/no_account"/>
|
||||
android:text="@string/no_account" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_registrasi"
|
||||
@ -99,7 +138,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/signup"
|
||||
android:textColor="@color/blue1"
|
||||
android:textStyle="bold"/>
|
||||
android:textStyle="bold" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@ -38,5 +38,6 @@
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toBottomOf="@id/linear_shipment"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -33,4 +33,23 @@
|
||||
tools:listitem="@layout/item_chat"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBarChat"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_empty_chat"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="16dp"
|
||||
android:gravity="center"
|
||||
android:visibility="gone"
|
||||
android:text="Keranjang Anda kosong"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="18sp" />
|
||||
|
||||
</LinearLayout>
|
@ -75,7 +75,7 @@
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Didn't receive the code? " />
|
||||
android:text="Belum menerima kode? " />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_resend_otp"
|
||||
|
@ -1,6 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
Reference in New Issue
Block a user