From d726c5ccc6463082dc38aace4783290ce687acb1 Mon Sep 17 00:00:00 2001 From: shaulascr Date: Mon, 19 May 2025 13:28:21 +0700 Subject: [PATCH] update ui --- .../data/api/dto/VerifRegisReq.kt | 11 + .../data/api/retrofit/ApiService.kt | 7 + .../data/repository/UserRepository.kt | 6 + .../ui/auth/RegisterActivity.kt | 315 +++++++++++----- .../ecommerce_serang/ui/chat/ChatActivity.kt | 23 +- .../ecommerce_serang/ui/chat/ChatFragment.kt | 337 ------------------ .../ui/chat/ChatListFragment.kt | 8 +- .../ecommerce_serang/ui/chat/ChatViewModel.kt | 6 + .../ui/order/history/OrderHistoryAdapter.kt | 16 +- .../ui/order/history/OrderHistoryFragment.kt | 8 +- .../ui/order/history/OrderViewPageAdapter.kt | 2 - .../detailorder/DetailOrderStatusActivity.kt | 78 +++- .../ui/product/DetailProductActivity.kt | 3 +- .../alya/ecommerce_serang/utils/Constants.kt | 1 + .../utils/viewmodel/ProfileViewModel.kt | 2 + .../utils/viewmodel/RegisterViewModel.kt | 25 ++ app/src/main/res/layout/fragment_home.xml | 6 +- app/src/main/res/layout/fragment_profile.xml | 1 + .../res/layout/item_product_horizontal.xml | 9 +- app/src/main/res/layout/view_search.xml | 1 + app/src/main/res/values/styles.xml | 2 +- 21 files changed, 409 insertions(+), 458 deletions(-) create mode 100644 app/src/main/java/com/alya/ecommerce_serang/data/api/dto/VerifRegisReq.kt delete mode 100644 app/src/main/java/com/alya/ecommerce_serang/ui/chat/ChatFragment.kt diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/VerifRegisReq.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/VerifRegisReq.kt new file mode 100644 index 0000000..3b1054d --- /dev/null +++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/VerifRegisReq.kt @@ -0,0 +1,11 @@ +package com.alya.ecommerce_serang.data.api.dto + +import com.google.gson.annotations.SerializedName + +data class VerifRegisReq ( + @SerializedName("field") + val fieldRegis: String, + + @SerializedName("value") + val valueRegis: String +) \ No newline at end of file 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 51ec55e..7a29fee 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 @@ -21,6 +21,7 @@ import com.alya.ecommerce_serang.data.api.dto.ShippingServiceRequest import com.alya.ecommerce_serang.data.api.dto.StoreAddressResponse import com.alya.ecommerce_serang.data.api.dto.UpdateCart import com.alya.ecommerce_serang.data.api.dto.UpdateChatRequest +import com.alya.ecommerce_serang.data.api.dto.VerifRegisReq import com.alya.ecommerce_serang.data.api.response.auth.CheckStoreResponse import com.alya.ecommerce_serang.data.api.response.auth.HasStoreResponse import com.alya.ecommerce_serang.data.api.response.auth.ListStoreTypeResponse @@ -28,6 +29,7 @@ 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 import com.alya.ecommerce_serang.data.api.response.auth.RegisterStoreResponse +import com.alya.ecommerce_serang.data.api.response.auth.VerifRegisterResponse import com.alya.ecommerce_serang.data.api.response.chat.ChatHistoryResponse import com.alya.ecommerce_serang.data.api.response.chat.ChatListResponse import com.alya.ecommerce_serang.data.api.response.chat.SendChatResponse @@ -88,6 +90,11 @@ interface ApiService { @Body registerRequest: RegisterRequest ): Response + @POST("verif") + suspend fun verifValue ( + @Body verifRegisReq: VerifRegisReq + ):VerifRegisterResponse + @GET("checkstore") suspend fun checkStore (): Response diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/repository/UserRepository.kt b/app/src/main/java/com/alya/ecommerce_serang/data/repository/UserRepository.kt index 8f16c34..6bc9881 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/data/repository/UserRepository.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/data/repository/UserRepository.kt @@ -7,11 +7,13 @@ import com.alya.ecommerce_serang.data.api.dto.LoginRequest import com.alya.ecommerce_serang.data.api.dto.OtpRequest import com.alya.ecommerce_serang.data.api.dto.RegisterRequest import com.alya.ecommerce_serang.data.api.dto.UserProfile +import com.alya.ecommerce_serang.data.api.dto.VerifRegisReq import com.alya.ecommerce_serang.data.api.response.auth.HasStoreResponse import com.alya.ecommerce_serang.data.api.response.auth.ListStoreTypeResponse 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.RegisterStoreResponse +import com.alya.ecommerce_serang.data.api.response.auth.VerifRegisterResponse import com.alya.ecommerce_serang.data.api.response.customer.order.ListCityResponse import com.alya.ecommerce_serang.data.api.response.customer.order.ListProvinceResponse import com.alya.ecommerce_serang.data.api.response.customer.profile.EditProfileResponse @@ -332,6 +334,10 @@ class UserRepository(private val apiService: ApiService) { return apiService.checkStoreUser() } + suspend fun checkValue(request: VerifRegisReq): VerifRegisterResponse{ + return apiService.verifValue(request) + } + companion object{ private const val TAG = "UserRepository" } 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 72d1e1a..f07dcd4 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 @@ -12,6 +12,7 @@ import androidx.core.view.ViewCompat import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat import com.alya.ecommerce_serang.data.api.dto.RegisterRequest +import com.alya.ecommerce_serang.data.api.dto.VerifRegisReq import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig import com.alya.ecommerce_serang.data.repository.Result import com.alya.ecommerce_serang.data.repository.UserRepository @@ -27,6 +28,17 @@ import java.util.Locale class RegisterActivity : AppCompatActivity() { private lateinit var binding: ActivityRegisterBinding private lateinit var sessionManager: SessionManager + + private var isEmailValid = false + private var isPhoneValid = false + + // Track which validation was last performed + private var lastCheckField = "" + + // Counter for signup validation + private var signupValidationsComplete = 0 + private var signupInProgress = false + private val registerViewModel: RegisterViewModel by viewModels{ BaseViewModelFactory { val apiService = ApiConfig.getUnauthenticatedApiService() @@ -76,107 +88,248 @@ class RegisterActivity : AppCompatActivity() { windowInsets } + setupObservers() - // Observe OTP state - observeOtpState() + // Set up field validations + setupFieldValidations() binding.btnSignup.setOnClickListener { - // Retrieve values inside the click listener (so we get latest input) - val birthDate = binding.etBirthDate.text.toString() - val email = binding.etEmail.text.toString() - val password = binding.etPassword.text.toString() - val phone = binding.etNumberPhone.text.toString() - val username = binding.etUsername.text.toString() - val name = binding.etFullname.text.toString() - val image = null - - val userData = RegisterRequest(name, email, password, username, phone, birthDate, image) - - Log.d("RegisterActivity", "Requesting OTP for email: $email") - - // Request OTP and wait for success before showing dialog - registerViewModel.requestOtp(userData.email.toString()) - - // Observe OTP state and show OTP dialog only when successful - registerViewModel.otpState.observe(this) { result -> - when (result) { - is Result.Success -> { - Log.d("RegisterActivity", "OTP sent successfully. Showing OTP dialog.") - // Show OTP dialog after OTP is successfully sent - val otpBottomSheet = OtpBottomSheetDialog(userData) { fullUserData -> - Log.d("RegisterActivity", "OTP entered successfully. Proceeding with registration.") - registerViewModel.registerUser(fullUserData) // Send complete data - } - otpBottomSheet.show(supportFragmentManager, "OtpBottomSheet") - } - is Result.Error -> { - // Show error message if OTP request fails - Log.e("RegisterActivity", "Failed to request OTP: ${result.exception.message}") - Toast.makeText(this, "Failed to request OTP: ${result.exception.message}", Toast.LENGTH_LONG).show() - } - is Result.Loading -> { - // Optional: Show loading indicator - } - } - } - - // Observe Register state - observeRegisterState() + handleSignUp() } - binding.tvLoginAlt.setOnClickListener{ + binding.tvLoginAlt.setOnClickListener { val intent = Intent(this, LoginActivity::class.java) startActivity(intent) } - binding.etBirthDate.setOnClickListener{ + binding.etBirthDate.setOnClickListener { showDatePicker() } } - private fun observeOtpState() { - registerViewModel.otpState.observe(this) { result -> - when (result) { - is Result.Loading -> { - // Show loading indicator - binding.progressBarOtp.visibility = android.view.View.VISIBLE - } - is Result.Success -> { - // Hide loading indicator and show success message - binding.progressBarOtp.visibility = android.view.View.GONE -// Toast.makeText(this@RegisterActivity, result.data, Toast.LENGTH_SHORT).show() - } - is Result.Error -> { - // Hide loading indicator and show error message - binding.progressBarOtp.visibility = android.view.View.GONE - Toast.makeText(this, "OTP Request Failed: ${result.exception.message}", Toast.LENGTH_SHORT).show() - } + private fun setupFieldValidations() { + // Validate email when focus changes + binding.etEmail.setOnFocusChangeListener { _, hasFocus -> + if (!hasFocus) { + val email = binding.etEmail.text.toString() + if (email.isNotEmpty()) { + validateEmail(email, false) } } + } + + // Validate phone when focus changes + binding.etNumberPhone.setOnFocusChangeListener { _, hasFocus -> + if (!hasFocus) { + val phone = binding.etNumberPhone.text.toString() + if (phone.isNotEmpty()) { + validatePhone(phone, false) + } + } + } } - private fun observeRegisterState() { - registerViewModel.registerState.observe(this) { result -> - when (result) { - is Result.Loading -> { - // Show loading indicator for registration - binding.progressBarRegister.visibility = android.view.View.VISIBLE + private fun validateEmail(email: String, isSignup: Boolean) { + lastCheckField = "email" + Log.d("RegisterActivity", "Validating email: $email (signup: $isSignup)") + + val checkValueEmail = VerifRegisReq( + fieldRegis = "email", + valueRegis = email + ) + registerViewModel.checkValueReg(checkValueEmail) + } + + private fun validatePhone(phone: String, isSignup: Boolean) { + lastCheckField = "phone" + Log.d("RegisterActivity", "Validating phone: $phone (signup: $isSignup)") + + val checkValuePhone = VerifRegisReq( + fieldRegis = "phone", + valueRegis = phone + ) + registerViewModel.checkValueReg(checkValuePhone) + } + + private fun setupObservers() { + + registerViewModel.checkValue.observe(this) { result -> + when (result) { + is Result.Loading -> { + // Show loading if needed + } + is Result.Success -> { + val isValid = (result.data as? Boolean) ?: false + + when (lastCheckField) { + "email" -> { + isEmailValid = isValid + if (!isValid) { + Toast.makeText(this, "Email is already registered", Toast.LENGTH_SHORT).show() + } else { + Log.d("RegisterActivity", "Email is valid") + } + } + "phone" -> { + isPhoneValid = isValid + if (!isValid) { + Toast.makeText(this, "Phone number is already registered", Toast.LENGTH_SHORT).show() + } else { + Log.d("RegisterActivity", "Phone is valid") + } + } } - is Result.Success -> { - // Hide loading indicator and show success message - binding.progressBarRegister.visibility = android.view.View.GONE - Toast.makeText(this, result.data, Toast.LENGTH_SHORT).show() - val intent = Intent(this, LoginActivity::class.java) - startActivity(intent) - // Navigate to another screen if needed - } - is com.alya.ecommerce_serang.data.repository.Result.Error -> { - // Hide loading indicator and show error message - binding.progressBarRegister.visibility = android.view.View.GONE - Toast.makeText(this, "Registration Failed: ${result.exception.message}", Toast.LENGTH_SHORT).show() + + // Check if we're in signup process + if (signupInProgress) { + signupValidationsComplete++ + + // Check if both validations completed + if (signupValidationsComplete >= 2) { + signupInProgress = false + signupValidationsComplete = 0 + + // If both validations passed, request OTP + if (isEmailValid && isPhoneValid) { + requestOtp() + } + } } } + is Result.Error -> { + val fieldType = if (lastCheckField == "email") "Email" else "Phone" + Toast.makeText(this, "$fieldType validation failed: ${result.exception.message}", Toast.LENGTH_SHORT).show() + + // Mark validation as invalid + if (lastCheckField == "email") { + isEmailValid = false + } else if (lastCheckField == "phone") { + isPhoneValid = false + } + + // Update signup validation counter if in signup process + if (signupInProgress) { + signupValidationsComplete++ + + // Check if both validations completed + if (signupValidationsComplete >= 2) { + signupInProgress = false + signupValidationsComplete = 0 + } + } + } + else -> { + Log.e("RegisterActivity", "Unexpected result type: $result") + } } + } + registerViewModel.otpState.observe(this) { result -> + when (result) { + is Result.Loading -> { + binding.progressBarOtp.visibility = android.view.View.VISIBLE + } + is Result.Success -> { + binding.progressBarOtp.visibility = android.view.View.GONE + Log.d("RegisterActivity", "OTP sent successfully. Showing OTP dialog.") + + // Create user data before showing OTP dialog + val userData = createUserData() + + // Show OTP dialog + val otpBottomSheet = OtpBottomSheetDialog(userData) { fullUserData -> + Log.d("RegisterActivity", "OTP entered successfully. Proceeding with registration.") + registerViewModel.registerUser(fullUserData) + } + otpBottomSheet.show(supportFragmentManager, "OtpBottomSheet") + } + is Result.Error -> { + binding.progressBarOtp.visibility = android.view.View.GONE + Toast.makeText(this, "OTP Request Failed: ${result.exception.message}", Toast.LENGTH_SHORT).show() + } + else -> { + Log.e("RegisterActivity", "Unexpected result type: $result") + } + } + } + registerViewModel.registerState.observe(this) { result -> + when (result) { + is Result.Loading -> { + // Show loading indicator for registration + binding.progressBarRegister.visibility = android.view.View.VISIBLE + } + is Result.Success -> { + // Hide loading indicator and show success message + binding.progressBarRegister.visibility = android.view.View.GONE + Toast.makeText(this, result.data, Toast.LENGTH_SHORT).show() + val intent = Intent(this, LoginActivity::class.java) + startActivity(intent) + // Navigate to another screen if needed + } + is com.alya.ecommerce_serang.data.repository.Result.Error -> { + // Hide loading indicator and show error message + binding.progressBarRegister.visibility = android.view.View.GONE + Toast.makeText(this, "Registration Failed: ${result.exception.message}", Toast.LENGTH_SHORT).show() + } + } + } + } + + private fun handleSignUp() { + // Basic validation first + val email = binding.etEmail.text.toString() + val password = binding.etPassword.text.toString() + val confirmPassword = binding.etConfirmPassword.text.toString() + val phone = binding.etNumberPhone.text.toString() + val username = binding.etUsername.text.toString() + val name = binding.etFullname.text.toString() + val birthDate = binding.etBirthDate.text.toString() + + // Check if fields are filled + if (email.isEmpty() || password.isEmpty() || confirmPassword.isEmpty() || + phone.isEmpty() || username.isEmpty() || name.isEmpty() || birthDate.isEmpty()) { + Toast.makeText(this, "Please fill all required fields", Toast.LENGTH_SHORT).show() + return + } + + // Check if passwords match + if (password != confirmPassword) { + Toast.makeText(this, "Passwords do not match", Toast.LENGTH_SHORT).show() + return + } + + // If both validations are already done and successful, just request OTP + if (isEmailValid && isPhoneValid) { + requestOtp() + return + } + + // Reset validation counters + signupInProgress = true + signupValidationsComplete = 0 + + // Start validations in parallel + validateEmail(email, true) + validatePhone(phone, true) + } + + private fun requestOtp() { + val email = binding.etEmail.text.toString() + Log.d("RegisterActivity", "Requesting OTP for email: $email") + registerViewModel.requestOtp(email) + } + + private fun createUserData(): RegisterRequest { + // Get all form values + val birthDate = binding.etBirthDate.text.toString() + val email = binding.etEmail.text.toString() + val password = binding.etPassword.text.toString() + val phone = binding.etNumberPhone.text.toString() + val username = binding.etUsername.text.toString() + val name = binding.etFullname.text.toString() + val image = null + + // Create and return user data object + return RegisterRequest(name, email, password, username, phone, birthDate, image) } private fun showDatePicker() { @@ -189,7 +342,7 @@ class RegisterActivity : AppCompatActivity() { this, { _, selectedYear, selectedMonth, selectedDay -> calendar.set(selectedYear, selectedMonth, selectedDay) - val sdf = SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()) + val sdf = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) binding.etBirthDate.setText(sdf.format(calendar.time)) }, year, month, day 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 907d4bb..0d61401 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 @@ -125,6 +125,7 @@ class ChatActivity : AppCompatActivity() { val productRating = intent.getFloatExtra(Constants.EXTRA_PRODUCT_RATING, 0f) val storeName = intent.getStringExtra(Constants.EXTRA_STORE_NAME) ?: "" val chatRoomId = intent.getIntExtra(Constants.EXTRA_CHAT_ROOM_ID, 0) + val storeImg = intent.getStringExtra(Constants.EXTRA_STORE_IMAGE) ?: "" // Check if user is logged in val token = sessionManager.getToken() @@ -137,7 +138,20 @@ class ChatActivity : AppCompatActivity() { return } - // Set chat parameters to ViewModel + binding.tvStoreName.text = storeName + val fullImageUrl = when (val img = storeImg) { + is String -> { + if (img.startsWith("/")) BASE_URL + img.substring(1) else img + } + else -> R.drawable.placeholder_image + } + + Glide.with(this) + .load(fullImageUrl) + .placeholder(R.drawable.placeholder_image) + .into(binding.imgProfile) + + // Set chat parameters to ViewModel viewModel.setChatParameters( storeId = storeId, productId = productId, @@ -227,6 +241,7 @@ class ChatActivity : AppCompatActivity() { } }) + // Observe state changes using LiveData viewModel.state.observe(this, Observer { state -> // Update messages @@ -244,6 +259,7 @@ class ChatActivity : AppCompatActivity() { binding.ratingBar.rating = state.productRating binding.tvRating.text = state.productRating.toString() binding.tvSellerName.text = state.storeName + binding.tvStoreName.text=state.storeName // Load product image if (!state.productImageUrl.isNullOrEmpty()) { @@ -270,6 +286,7 @@ class ChatActivity : AppCompatActivity() { binding.editTextMessage.hint = getString(R.string.write_message) } + // Show typing indicator binding.tvTypingIndicator.visibility = if (state.isOtherUserTyping) View.VISIBLE else View.GONE @@ -467,7 +484,8 @@ class ChatActivity : AppCompatActivity() { productImage: String? = null, productRating: String? = null, storeName: String? = null, - chatRoomId: Int = 0 + chatRoomId: Int = 0, + storeImage: String? = null ) { val intent = Intent(context, ChatActivity::class.java).apply { putExtra(Constants.EXTRA_STORE_ID, storeId) @@ -475,6 +493,7 @@ class ChatActivity : AppCompatActivity() { putExtra(Constants.EXTRA_PRODUCT_NAME, productName) putExtra(Constants.EXTRA_PRODUCT_PRICE, productPrice) putExtra(Constants.EXTRA_PRODUCT_IMAGE, productImage) + putExtra(Constants.EXTRA_STORE_IMAGE, storeImage) // Convert productRating string to float if provided if (productRating != null) { diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/chat/ChatFragment.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/chat/ChatFragment.kt deleted file mode 100644 index 4bd12ae..0000000 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/chat/ChatFragment.kt +++ /dev/null @@ -1,337 +0,0 @@ -//package com.alya.ecommerce_serang.ui.chat -// -//import android.Manifest -//import android.app.Activity -//import android.content.Intent -//import android.content.pm.PackageManager -//import android.net.Uri -//import android.os.Bundle -//import android.provider.MediaStore -//import android.text.Editable -//import android.text.TextWatcher -//import androidx.fragment.app.Fragment -//import android.view.LayoutInflater -//import android.view.View -//import android.view.ViewGroup -//import android.widget.Toast -//import androidx.activity.result.contract.ActivityResultContracts -//import androidx.core.app.ActivityCompat -//import androidx.core.content.ContextCompat -//import androidx.core.content.FileProvider -//import androidx.fragment.app.viewModels -//import androidx.lifecycle.lifecycleScope -//import androidx.navigation.fragment.navArgs -//import androidx.recyclerview.widget.LinearLayoutManager -//import com.alya.ecommerce_serang.BuildConfig.BASE_URL -//import com.alya.ecommerce_serang.R -//import com.alya.ecommerce_serang.databinding.FragmentChatBinding -//import com.alya.ecommerce_serang.utils.Constants -//import com.bumptech.glide.Glide -//import dagger.hilt.android.AndroidEntryPoint -//import kotlinx.coroutines.launch -//import java.io.File -//import java.text.SimpleDateFormat -//import java.util.Locale -// -//@AndroidEntryPoint -//class ChatFragment : Fragment() { -// -// private var _binding: FragmentChatBinding? = null -// private val binding get() = _binding!! -// -// private val viewModel: ChatViewModel by viewModels() -//// private val args: ChatFragmentArgs by navArgs() -// -// private lateinit var chatAdapter: ChatAdapter -// -// // For image attachment -// private var tempImageUri: Uri? = null -// -// // Typing indicator handler -// private val typingHandler = android.os.Handler(android.os.Looper.getMainLooper()) -// private val stopTypingRunnable = Runnable { -// viewModel.sendTypingStatus(false) -// } -// -// // Activity Result Launchers -// private val pickImageLauncher = registerForActivityResult( -// ActivityResultContracts.StartActivityForResult() -// ) { result -> -// if (result.resultCode == Activity.RESULT_OK) { -// result.data?.data?.let { uri -> -// handleSelectedImage(uri) -// } -// } -// } -// -// private val takePictureLauncher = registerForActivityResult( -// ActivityResultContracts.StartActivityForResult() -// ) { result -> -// if (result.resultCode == Activity.RESULT_OK) { -// tempImageUri?.let { uri -> -// handleSelectedImage(uri) -// } -// } -// } -// -// override fun onCreateView( -// inflater: LayoutInflater, -// container: ViewGroup?, -// savedInstanceState: Bundle? -// ): View { -// _binding = FragmentChatBinding.inflate(inflater, container, false) -// return binding.root -// } -// -// override fun onViewCreated(view: View, savedInstanceState: Bundle?) { -// super.onViewCreated(view, savedInstanceState) -// -// setupRecyclerView() -// setupListeners() -// setupTypingIndicator() -// observeViewModel() -// } -// -// private fun setupRecyclerView() { -// chatAdapter = ChatAdapter() -// binding.recyclerChat.apply { -// adapter = chatAdapter -// layoutManager = LinearLayoutManager(requireContext()).apply { -// stackFromEnd = true -// } -// } -// } -// -// private fun setupListeners() { -// // Back button -// binding.btnBack.setOnClickListener { -// requireActivity().onBackPressed() -// } -// -// // Options button -// binding.btnOptions.setOnClickListener { -// showOptionsMenu() -// } -// -// // Send button -// binding.btnSend.setOnClickListener { -// val message = binding.editTextMessage.text.toString().trim() -// if (message.isNotEmpty() || viewModel.state.value.hasAttachment) { -// viewModel.sendMessage(message) -// binding.editTextMessage.text.clear() -// } -// } -// -// // Attachment button -// binding.btnAttachment.setOnClickListener { -// checkPermissionsAndShowImagePicker() -// } -// } -// -// private fun setupTypingIndicator() { -// binding.editTextMessage.addTextChangedListener(object : TextWatcher { -// override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} -// -// override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { -// viewModel.sendTypingStatus(true) -// -// // Reset the timer -// typingHandler.removeCallbacks(stopTypingRunnable) -// typingHandler.postDelayed(stopTypingRunnable, 1000) -// } -// -// override fun afterTextChanged(s: Editable?) {} -// }) -// } -// -// private fun observeViewModel() { -// viewLifecycleOwner.lifecycleScope.launch { -// viewModel.state.collectLatest { state -> -// // Update messages -// chatAdapter.submitList(state.messages) -// -// // Scroll to bottom if new message -// if (state.messages.isNotEmpty()) { -// binding.recyclerChat.scrollToPosition(state.messages.size - 1) -// } -// -// // Update product info -// binding.tvProductName.text = state.productName -// binding.tvProductPrice.text = state.productPrice -// binding.ratingBar.rating = state.productRating -// binding.tvRating.text = state.productRating.toString() -// binding.tvSellerName.text = state.storeName -// -// // Load product image -// if (state.productImageUrl.isNotEmpty()) { -// Glide.with(requireContext()) -// .load(BASE_URL + state.productImageUrl) -// .centerCrop() -// .placeholder(R.drawable.placeholder_image) -// .error(R.drawable.placeholder_image) -// .into(binding.imgProduct) -// } -// -// // Show/hide loading indicators -// binding.progressBar.visibility = if (state.isLoading) View.VISIBLE else View.GONE -// binding.btnSend.isEnabled = !state.isSending -// -// // Update attachment hint -// if (state.hasAttachment) { -// binding.editTextMessage.hint = getString(R.string.image_attached) -// } else { -// binding.editTextMessage.hint = getString(R.string.write_message) -// } -// -// // Show typing indicator -// binding.tvTypingIndicator.visibility = -// if (state.isOtherUserTyping) View.VISIBLE else View.GONE -// -// // Handle connection state -// handleConnectionState(state.connectionState) -// -// // Show error if any -// state.error?.let { error -> -// Toast.makeText(requireContext(), error, Toast.LENGTH_SHORT).show() -// viewModel.clearError() -// } -// } -// } -// } -// -// private fun handleConnectionState(state: ConnectionState) { -// when (state) { -// is ConnectionState.Connected -> { -// binding.tvConnectionStatus.visibility = View.GONE -// } -// is ConnectionState.Connecting -> { -// binding.tvConnectionStatus.visibility = View.VISIBLE -// binding.tvConnectionStatus.text = getString(R.string.connecting) -// } -// is ConnectionState.Disconnected -> { -// binding.tvConnectionStatus.visibility = View.VISIBLE -// binding.tvConnectionStatus.text = getString(R.string.disconnected_reconnecting) -// } -// is ConnectionState.Error -> { -// binding.tvConnectionStatus.visibility = View.VISIBLE -// binding.tvConnectionStatus.text = getString(R.string.connection_error, state.message) -// } -// } -// } -// -// private fun showOptionsMenu() { -// val options = arrayOf( -// getString(R.string.block_user), -// getString(R.string.report), -// getString(R.string.clear_chat), -// getString(R.string.cancel) -// ) -// -// androidx.appcompat.app.AlertDialog.Builder(requireContext()) -// .setTitle(getString(R.string.options)) -// .setItems(options) { dialog, which -> -// when (which) { -// 0 -> Toast.makeText(requireContext(), R.string.block_user_selected, Toast.LENGTH_SHORT).show() -// 1 -> Toast.makeText(requireContext(), R.string.report_selected, Toast.LENGTH_SHORT).show() -// 2 -> Toast.makeText(requireContext(), R.string.clear_chat_selected, Toast.LENGTH_SHORT).show() -// } -// dialog.dismiss() -// } -// .show() -// } -// -// private fun checkPermissionsAndShowImagePicker() { -// if (ContextCompat.checkSelfPermission( -// requireContext(), -// Manifest.permission.READ_EXTERNAL_STORAGE -// ) != PackageManager.PERMISSION_GRANTED -// ) { -// ActivityCompat.requestPermissions( -// requireActivity(), -// arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA), -// Constants.REQUEST_STORAGE_PERMISSION -// ) -// } else { -// showImagePickerOptions() -// } -// } -// -// private fun showImagePickerOptions() { -// val options = arrayOf( -// getString(R.string.take_photo), -// getString(R.string.choose_from_gallery), -// getString(R.string.cancel) -// ) -// -// androidx.appcompat.app.AlertDialog.Builder(requireContext()) -// .setTitle(getString(R.string.select_attachment)) -// .setItems(options) { dialog, which -> -// when (which) { -// 0 -> openCamera() -// 1 -> openGallery() -// } -// dialog.dismiss() -// } -// .show() -// } -// -// private fun openCamera() { -// val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date()) -// val imageFileName = "IMG_${timeStamp}.jpg" -// val storageDir = requireContext().getExternalFilesDir(null) -// val imageFile = File(storageDir, imageFileName) -// -// tempImageUri = FileProvider.getUriForFile( -// requireContext(), -// "${requireContext().packageName}.fileprovider", -// imageFile -// ) -// -// val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE).apply { -// putExtra(MediaStore.EXTRA_OUTPUT, tempImageUri) -// } -// -// takePictureLauncher.launch(intent) -// } -// -// private fun openGallery() { -// val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) -// pickImageLauncher.launch(intent) -// } -// -// private fun handleSelectedImage(uri: Uri) { -// // Get the file from Uri -// val filePathColumn = arrayOf(MediaStore.Images.Media.DATA) -// val cursor = requireContext().contentResolver.query(uri, filePathColumn, null, null, null) -// cursor?.moveToFirst() -// val columnIndex = cursor?.getColumnIndex(filePathColumn[0]) -// val filePath = cursor?.getString(columnIndex ?: 0) -// cursor?.close() -// -// if (filePath != null) { -// viewModel.setSelectedImageFile(File(filePath)) -// Toast.makeText(requireContext(), R.string.image_selected, Toast.LENGTH_SHORT).show() -// } -// } -// -// override fun onRequestPermissionsResult( -// requestCode: Int, -// permissions: Array, -// grantResults: IntArray -// ) { -// super.onRequestPermissionsResult(requestCode, permissions, grantResults) -// if (requestCode == Constants.REQUEST_STORAGE_PERMISSION) { -// if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { -// showImagePickerOptions() -// } else { -// Toast.makeText(requireContext(), R.string.permission_denied, Toast.LENGTH_SHORT).show() -// } -// } -// } -// -// override fun onDestroyView() { -// super.onDestroyView() -// typingHandler.removeCallbacks(stopTypingRunnable) -// _binding = null -// } -//} \ No newline at end of file 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 4d395a2..ed2aa87 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 @@ -21,6 +21,7 @@ class ChatListFragment : Fragment() { private val binding get() = _binding!! private lateinit var socketService: SocketIOService private lateinit var sessionManager: SessionManager + private val viewModel: com.alya.ecommerce_serang.ui.chat.ChatViewModel by viewModels { BaseViewModelFactory { val apiService = ApiConfig.getApiService(sessionManager) @@ -65,7 +66,8 @@ class ChatListFragment : Fragment() { productImage = null, productRating = null, storeName = chatItem.storeName, - chatRoomId = chatItem.chatRoomId + chatRoomId = chatItem.chatRoomId, + storeImage = chatItem.storeImage ) } binding.chatListRecyclerView.adapter = adapter @@ -85,4 +87,8 @@ class ChatListFragment : Fragment() { super.onDestroyView() _binding = null } + + companion object{ + + } } \ No newline at end of file diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/chat/ChatViewModel.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/chat/ChatViewModel.kt index b5db71a..989dedd 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/chat/ChatViewModel.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/chat/ChatViewModel.kt @@ -8,6 +8,7 @@ import androidx.lifecycle.viewModelScope import com.alya.ecommerce_serang.data.api.response.chat.ChatItem import com.alya.ecommerce_serang.data.api.response.chat.ChatItemList import com.alya.ecommerce_serang.data.api.response.chat.ChatLine +import com.alya.ecommerce_serang.data.api.response.customer.product.StoreProduct import com.alya.ecommerce_serang.data.repository.ChatRepository import com.alya.ecommerce_serang.data.repository.Result import com.alya.ecommerce_serang.utils.Constants @@ -23,6 +24,8 @@ import javax.inject.Inject class ChatViewModel @Inject constructor( private val chatRepository: ChatRepository, private val socketService: SocketIOService, + + private val sessionManager: SessionManager ) : ViewModel() { @@ -38,6 +41,9 @@ class ChatViewModel @Inject constructor( private val _chatList = MutableLiveData>>() val chatList: LiveData>> = _chatList + private val _storeDetail = MutableLiveData>() + val storeDetail : LiveData> get() = _storeDetail + // Store and product parameters private var storeId: Int = 0 private var productId: Int? = 0 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 9857af3..5432f78 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 @@ -154,6 +154,7 @@ class OrderHistoryAdapter( text = itemView.context.getString(R.string.canceled_order_btn) setOnClickListener { showCancelOrderBottomSheet(order.orderId) + viewModel.refreshOrders() } } deadlineDate.apply { @@ -175,6 +176,7 @@ class OrderHistoryAdapter( text = itemView.context.getString(R.string.canceled_order_btn) setOnClickListener { showCancelOrderBottomSheet(order.orderId) + viewModel.refreshOrders() } } @@ -211,6 +213,7 @@ class OrderHistoryAdapter( text = itemView.context.getString(R.string.canceled_order_btn) setOnClickListener { showCancelOrderDialog(order.orderId.toString()) + viewModel.refreshOrders() } } } @@ -229,6 +232,7 @@ class OrderHistoryAdapter( text = itemView.context.getString(R.string.claim_complaint) setOnClickListener { showCancelOrderDialog(order.orderId.toString()) + viewModel.refreshOrders() } } btnRight.apply { @@ -237,6 +241,7 @@ class OrderHistoryAdapter( setOnClickListener { // Handle click event viewModel.confirmOrderCompleted(order.orderId, "completed") + viewModel.refreshOrders() } } @@ -245,16 +250,6 @@ class OrderHistoryAdapter( text = formatShipmentDate(order.updatedAt, order.etd ?: "0") } } - "delivered" -> { - // Untuk status delivered, tampilkan "Beri Ulasan" - btnRight.apply { - visibility = View.VISIBLE - text = itemView.context.getString(R.string.add_review) - setOnClickListener { - // Handle click event - } - } - } "completed" -> { statusOrder.apply { visibility = View.VISIBLE @@ -269,6 +264,7 @@ class OrderHistoryAdapter( text = itemView.context.getString(R.string.add_review) setOnClickListener { addReviewProduct(order) + viewModel.refreshOrders() // Handle click event } } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryFragment.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryFragment.kt index b7d0f6e..267eb28 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryFragment.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryFragment.kt @@ -47,11 +47,9 @@ class OrderHistoryFragment : Fragment() { 1 -> getString(R.string.pending_orders) 2 -> getString(R.string.unpaid_orders) 3 -> getString(R.string.processed_orders) - 4 -> getString(R.string.paid_orders) - 5 -> getString(R.string.shipped_orders) - 6 -> getString(R.string.delivered_orders) - 7 -> getString(R.string.completed_orders) - 8 -> getString(R.string.canceled_orders) + 4 -> getString(R.string.shipped_orders) + 5 -> getString(R.string.completed_orders) + 6 -> getString(R.string.canceled_orders) else -> "Tab $position" } }.attach() diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderViewPageAdapter.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderViewPageAdapter.kt index a759240..615f7a1 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderViewPageAdapter.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderViewPageAdapter.kt @@ -14,9 +14,7 @@ class OrderViewPagerAdapter( "pending", // Menunggu Tagihan "unpaid", // Belum Dibayar "processed", // Diproses - "paid", // Dibayar "shipped", // Dikirim - "delivered", // Diterima "completed", // Selesai "canceled" // Dibatalkan ) diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/detailorder/DetailOrderStatusActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/detailorder/DetailOrderStatusActivity.kt index 414e013..7eb7341 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/detailorder/DetailOrderStatusActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/detailorder/DetailOrderStatusActivity.kt @@ -33,6 +33,7 @@ import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig import com.alya.ecommerce_serang.data.repository.OrderRepository import com.alya.ecommerce_serang.databinding.ActivityDetailOrderStatusBinding import com.alya.ecommerce_serang.ui.order.detail.PaymentActivity +import com.alya.ecommerce_serang.ui.order.history.cancelorder.CancelOrderBottomSheet import com.alya.ecommerce_serang.ui.order.review.CreateReviewActivity import com.alya.ecommerce_serang.ui.product.ReviewProductActivity import com.alya.ecommerce_serang.utils.BaseViewModelFactory @@ -50,6 +51,7 @@ class DetailOrderStatusActivity : AppCompatActivity() { private lateinit var binding: ActivityDetailOrderStatusBinding private lateinit var sessionManager: SessionManager + private var orderId: Int = -1 private var orderStatus: String = "" private val orders = mutableListOf() @@ -181,9 +183,9 @@ class DetailOrderStatusActivity : AppCompatActivity() { setupProductsRecyclerView(orders.orderItems) // Set payment method - binding.tvPaymentMethod.text = "Bank Transfer - ${orders.payInfoName ?: "BCA"}" + binding.tvPaymentMethod.text = "Bank Transfer - ${orders.payInfoName ?: "Tidak tersedia"}" - Log.d(TAG, "populateOrderDetails: Payment method=${orders.payInfoName ?: "BCA"}") + Log.d(TAG, "populateOrderDetails: Payment method=${orders.payInfoName ?: "Tidak tersedia"}") // Set subtotal, shipping cost, and total val subtotal = orders.totalAmount?.toIntOrNull()?.minus(orders.shipmentPrice.toIntOrNull() ?: 0) ?: 0 @@ -237,10 +239,8 @@ class DetailOrderStatusActivity : AppCompatActivity() { Log.d(TAG, "adjustButtonsBasedOnStatus: Status header set to '$statusText'") when (status) { - "pending", "unpaid" -> { - Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for pending/unpaid order") - - // Show status note + "pending"->{ + binding.tvStatusHeader.text = "Menunggu Tagihan" binding.tvStatusNote.visibility = View.VISIBLE binding.tvStatusNote.text = "Pesanan ini harus dibayar sebelum ${formatDatePay(orders.updatedAt)}" @@ -250,7 +250,27 @@ class DetailOrderStatusActivity : AppCompatActivity() { text = "Batalkan Pesanan" setOnClickListener { Log.d(TAG, "Cancel Order button clicked") - showCancelOrderDialog(orders.orderId.toString()) + showCancelOrderBottomSheet(orders.orderId) + viewModel.getOrderDetails(orders.orderId) + } + } + } + "unpaid" -> { + Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for pending/unpaid order") + + // Show status note + binding.tvStatusHeader.text = "Belum Dibayar" + binding.tvStatusNote.visibility = View.VISIBLE + binding.tvStatusNote.text = "Pesanan ini harus dibayar sebelum ${formatDatePay(orders.updatedAt)}" + + // Set buttons + binding.btnSecondary.apply { + visibility = View.VISIBLE + text = "Batalkan Pesanan" + setOnClickListener { + Log.d(TAG, "Cancel Order button clicked") + showCancelOrderBottomSheet(orders.orderId) + viewModel.getOrderDetails(orders.orderId) } } @@ -270,6 +290,7 @@ class DetailOrderStatusActivity : AppCompatActivity() { "processed" -> { Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for processed order") + binding.tvStatusHeader.text = "Sedang Diproses" binding.tvStatusNote.visibility = View.VISIBLE binding.tvStatusNote.text = "Penjual sedang memproses pesanan Anda" @@ -279,13 +300,19 @@ class DetailOrderStatusActivity : AppCompatActivity() { setOnClickListener { Log.d(TAG, "Cancel Order button clicked for processed order") showCancelOrderDialog(orders.orderId.toString()) + viewModel.getOrderDetails(orders.orderId) } } + + binding.btnPrimary.apply { + visibility = View.GONE + } } "shipped" -> { Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for shipped order") + binding.tvStatusHeader.text = "Sudah Dikirim" binding.tvStatusNote.visibility = View.VISIBLE binding.tvStatusNote.text = "Pesanan Anda sedang dalam perjalanan. Akan sampai sekitar ${formatShipmentDate(orders.updatedAt, orders.etd ?: "0")}" @@ -294,7 +321,8 @@ class DetailOrderStatusActivity : AppCompatActivity() { text = "Ajukan Komplain" setOnClickListener { Log.d(TAG, "Complaint button clicked") - showCancelOrderDialog(orders.orderId.toString()) // For now, reuse the cancel dialog + showCancelOrderDialog(orders.orderId.toString()) + viewModel.getOrderDetails(orders.orderId) } } @@ -314,11 +342,11 @@ class DetailOrderStatusActivity : AppCompatActivity() { } } - "delivered", "completed" -> { + "completed" -> { Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for delivered/completed order") - binding.tvStatusNote.visibility = View.VISIBLE - binding.tvStatusNote.text = "Pesanan telah selesai" + binding.tvStatusHeader.text = "Pesanan Selesai" + binding.tvStatusNote.visibility = View.GONE binding.btnPrimary.apply { visibility = View.VISIBLE @@ -326,15 +354,27 @@ class DetailOrderStatusActivity : AppCompatActivity() { setOnClickListener { Log.d(TAG, "Review button clicked") addReviewForOrder(orders) + viewModel.getOrderDetails(orders.orderId) } } + binding.btnSecondary.apply { + visibility = View.GONE + } } "canceled" -> { Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for canceled order") + binding.tvStatusHeader.text = "Pesanan Selesai" binding.tvStatusNote.visibility = View.VISIBLE binding.tvStatusNote.text = "Pesanan dibatalkan: ${orders.cancelReason ?: "Alasan tidak diberikan"}" + + binding.btnSecondary.apply { + visibility = View.GONE + } + binding.btnPrimary.apply { + visibility = View.GONE + } } } } @@ -530,6 +570,22 @@ class DetailOrderStatusActivity : AppCompatActivity() { dialog.show() } + private fun showCancelOrderBottomSheet(orderId: Int) { + // Create and show the bottom sheet directly since we're already in an Activity + val bottomSheet = CancelOrderBottomSheet( + orderId = orderId, + onOrderCancelled = { + // Handle the successful cancellation + // Refresh the data + + // Show a success message + Toast.makeText(this, "Order cancelled successfully", Toast.LENGTH_SHORT).show() + } + ) + + bottomSheet.show(supportFragmentManager, CancelOrderBottomSheet.TAG) + } + private fun formatDate(dateString: String): String { Log.d(TAG, "formatDate: Formatting date: $dateString") diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/product/DetailProductActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/product/DetailProductActivity.kt index b06d44f..188913e 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/product/DetailProductActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/product/DetailProductActivity.kt @@ -414,7 +414,8 @@ class DetailProductActivity : AppCompatActivity() { productImage = productDetail.image, productRating = productDetail.rating, storeName = storeDetail.data.storeName, - chatRoomId = 0 + chatRoomId = 0, + storeImage = storeDetail.data.storeImage ) } diff --git a/app/src/main/java/com/alya/ecommerce_serang/utils/Constants.kt b/app/src/main/java/com/alya/ecommerce_serang/utils/Constants.kt index 02dcb5e..225725f 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/utils/Constants.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/utils/Constants.kt @@ -20,6 +20,7 @@ object Constants { const val EXTRA_PRODUCT_PRICE = "product_price" const val EXTRA_PRODUCT_IMAGE = "product_image" const val EXTRA_PRODUCT_RATING = "product_rating" + const val EXTRA_STORE_IMAGE = "store_image" // Request codes const val REQUEST_IMAGE_PICK = 1001 diff --git a/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/ProfileViewModel.kt b/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/ProfileViewModel.kt index 0ed92f4..da4552f 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/ProfileViewModel.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/ProfileViewModel.kt @@ -60,6 +60,8 @@ class ProfileViewModel(private val userRepository: UserRepository) : ViewModel() } } + + fun editProfileDirect( context: Context, username: String, 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 665660c..34f75ae 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 @@ -6,7 +6,9 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.alya.ecommerce_serang.data.api.dto.RegisterRequest +import com.alya.ecommerce_serang.data.api.dto.VerifRegisReq import com.alya.ecommerce_serang.data.api.response.auth.OtpResponse +import com.alya.ecommerce_serang.data.api.response.auth.VerifRegisterResponse import com.alya.ecommerce_serang.data.repository.Result import com.alya.ecommerce_serang.data.repository.UserRepository import kotlinx.coroutines.launch @@ -21,6 +23,9 @@ class RegisterViewModel(private val repository: UserRepository) : ViewModel() { private val _otpState = MutableLiveData>() val otpState: LiveData> = _otpState + private val _checkValue = MutableLiveData>() + val checkValue: LiveData> = _checkValue + // MutableLiveData to store messages from API responses private val _message = MutableLiveData() val message: LiveData = _message @@ -86,4 +91,24 @@ class RegisterViewModel(private val repository: UserRepository) : ViewModel() { } } } + + fun checkValueReg(request: VerifRegisReq){ + viewModelScope.launch { + try { + // Call the repository function to request OTP + val response: VerifRegisterResponse = repository.checkValue(request) + + // Log and store success message + Log.d("RegisterViewModel", "OTP Response: ${response.available}") + _checkValue.value = Result.Success(response.available)// Store the message for UI feedback + + } catch (exception: Exception) { + // Handle any errors and update state + _checkValue.value = Result.Error(exception) + + // Log the error for debugging + Log.e("RegisterViewModel", "Error:", exception) + } + } + } } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index be25e39..8181a09 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -49,7 +49,7 @@ android:text="@string/fragment_home_categories" android:textColor="@color/blue_500" android:fontFamily="@font/dmsans_bold" - android:textSize="22sp" + android:textSize="18sp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/banners" /> @@ -89,7 +89,7 @@ android:text="@string/sold_product_text" android:textColor="@color/blue_500" android:fontFamily="@font/dmsans_bold" - android:textSize="22sp" + android:textSize="18sp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/categories" /> diff --git a/app/src/main/res/layout/fragment_profile.xml b/app/src/main/res/layout/fragment_profile.xml index 182886f..c99ee71 100644 --- a/app/src/main/res/layout/fragment_profile.xml +++ b/app/src/main/res/layout/fragment_profile.xml @@ -16,6 +16,7 @@ android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:src="@drawable/outline_account_circle_24" + android:scaleType="centerCrop" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> diff --git a/app/src/main/res/layout/item_product_horizontal.xml b/app/src/main/res/layout/item_product_horizontal.xml index dbc3c43..6f38ce8 100644 --- a/app/src/main/res/layout/item_product_horizontal.xml +++ b/app/src/main/res/layout/item_product_horizontal.xml @@ -7,11 +7,12 @@ @@ -32,7 +33,7 @@ android:text="Banana" android:textColor="@color/black" android:fontFamily="@font/dmsans_medium" - android:textSize="18sp" + android:textSize="16sp" app:layout_constraintTop_toBottomOf="@id/imageLayout" /> diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index dcf0226..b72680e 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -48,7 +48,7 @@