mirror of
https://github.com/shaulascr/ecommerce_serang.git
synced 2025-08-13 18:52:20 +00:00
update ui
This commit is contained in:
@ -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
|
||||||
|
)
|
@ -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.StoreAddressResponse
|
||||||
import com.alya.ecommerce_serang.data.api.dto.UpdateCart
|
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.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.CheckStoreResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.auth.HasStoreResponse
|
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.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.OtpResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.auth.RegisterResponse
|
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.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.ChatHistoryResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.chat.ChatListResponse
|
import com.alya.ecommerce_serang.data.api.response.chat.ChatListResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.chat.SendChatResponse
|
import com.alya.ecommerce_serang.data.api.response.chat.SendChatResponse
|
||||||
@ -88,6 +90,11 @@ interface ApiService {
|
|||||||
@Body registerRequest: RegisterRequest
|
@Body registerRequest: RegisterRequest
|
||||||
): Response<RegisterResponse>
|
): Response<RegisterResponse>
|
||||||
|
|
||||||
|
@POST("verif")
|
||||||
|
suspend fun verifValue (
|
||||||
|
@Body verifRegisReq: VerifRegisReq
|
||||||
|
):VerifRegisterResponse
|
||||||
|
|
||||||
@GET("checkstore")
|
@GET("checkstore")
|
||||||
suspend fun checkStore (): Response<CheckStoreResponse>
|
suspend fun checkStore (): Response<CheckStoreResponse>
|
||||||
|
|
||||||
|
@ -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.OtpRequest
|
||||||
import com.alya.ecommerce_serang.data.api.dto.RegisterRequest
|
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.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.HasStoreResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.auth.ListStoreTypeResponse
|
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.LoginResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.auth.OtpResponse
|
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.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.ListCityResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.customer.order.ListProvinceResponse
|
import com.alya.ecommerce_serang.data.api.response.customer.order.ListProvinceResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.customer.profile.EditProfileResponse
|
import com.alya.ecommerce_serang.data.api.response.customer.profile.EditProfileResponse
|
||||||
@ -332,6 +334,10 @@ class UserRepository(private val apiService: ApiService) {
|
|||||||
return apiService.checkStoreUser()
|
return apiService.checkStoreUser()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun checkValue(request: VerifRegisReq): VerifRegisterResponse{
|
||||||
|
return apiService.verifValue(request)
|
||||||
|
}
|
||||||
|
|
||||||
companion object{
|
companion object{
|
||||||
private const val TAG = "UserRepository"
|
private const val TAG = "UserRepository"
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import androidx.core.view.ViewCompat
|
|||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import com.alya.ecommerce_serang.data.api.dto.RegisterRequest
|
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.api.retrofit.ApiConfig
|
||||||
import com.alya.ecommerce_serang.data.repository.Result
|
import com.alya.ecommerce_serang.data.repository.Result
|
||||||
import com.alya.ecommerce_serang.data.repository.UserRepository
|
import com.alya.ecommerce_serang.data.repository.UserRepository
|
||||||
@ -27,6 +28,17 @@ import java.util.Locale
|
|||||||
class RegisterActivity : AppCompatActivity() {
|
class RegisterActivity : AppCompatActivity() {
|
||||||
private lateinit var binding: ActivityRegisterBinding
|
private lateinit var binding: ActivityRegisterBinding
|
||||||
private lateinit var sessionManager: SessionManager
|
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{
|
private val registerViewModel: RegisterViewModel by viewModels{
|
||||||
BaseViewModelFactory {
|
BaseViewModelFactory {
|
||||||
val apiService = ApiConfig.getUnauthenticatedApiService()
|
val apiService = ApiConfig.getUnauthenticatedApiService()
|
||||||
@ -76,52 +88,13 @@ class RegisterActivity : AppCompatActivity() {
|
|||||||
windowInsets
|
windowInsets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setupObservers()
|
||||||
|
|
||||||
// Observe OTP state
|
// Set up field validations
|
||||||
observeOtpState()
|
setupFieldValidations()
|
||||||
|
|
||||||
binding.btnSignup.setOnClickListener {
|
binding.btnSignup.setOnClickListener {
|
||||||
// Retrieve values inside the click listener (so we get latest input)
|
handleSignUp()
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.tvLoginAlt.setOnClickListener {
|
binding.tvLoginAlt.setOnClickListener {
|
||||||
@ -134,28 +107,150 @@ class RegisterActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun observeOtpState() {
|
private fun setupFieldValidations() {
|
||||||
registerViewModel.otpState.observe(this) { result ->
|
// Validate email when focus changes
|
||||||
when (result) {
|
binding.etEmail.setOnFocusChangeListener { _, hasFocus ->
|
||||||
is Result.Loading -> {
|
if (!hasFocus) {
|
||||||
// Show loading indicator
|
val email = binding.etEmail.text.toString()
|
||||||
binding.progressBarOtp.visibility = android.view.View.VISIBLE
|
if (email.isNotEmpty()) {
|
||||||
|
validateEmail(email, false)
|
||||||
}
|
}
|
||||||
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
|
// Validate phone when focus changes
|
||||||
Toast.makeText(this, "OTP Request Failed: ${result.exception.message}", Toast.LENGTH_SHORT).show()
|
binding.etNumberPhone.setOnFocusChangeListener { _, hasFocus ->
|
||||||
|
if (!hasFocus) {
|
||||||
|
val phone = binding.etNumberPhone.text.toString()
|
||||||
|
if (phone.isNotEmpty()) {
|
||||||
|
validatePhone(phone, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun observeRegisterState() {
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 ->
|
registerViewModel.registerState.observe(this) { result ->
|
||||||
when (result) {
|
when (result) {
|
||||||
is Result.Loading -> {
|
is Result.Loading -> {
|
||||||
@ -179,6 +274,64 @@ class RegisterActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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() {
|
private fun showDatePicker() {
|
||||||
val calendar = Calendar.getInstance()
|
val calendar = Calendar.getInstance()
|
||||||
val year = calendar.get(Calendar.YEAR)
|
val year = calendar.get(Calendar.YEAR)
|
||||||
@ -189,7 +342,7 @@ class RegisterActivity : AppCompatActivity() {
|
|||||||
this,
|
this,
|
||||||
{ _, selectedYear, selectedMonth, selectedDay ->
|
{ _, selectedYear, selectedMonth, selectedDay ->
|
||||||
calendar.set(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))
|
binding.etBirthDate.setText(sdf.format(calendar.time))
|
||||||
},
|
},
|
||||||
year, month, day
|
year, month, day
|
||||||
|
@ -125,6 +125,7 @@ class ChatActivity : AppCompatActivity() {
|
|||||||
val productRating = intent.getFloatExtra(Constants.EXTRA_PRODUCT_RATING, 0f)
|
val productRating = intent.getFloatExtra(Constants.EXTRA_PRODUCT_RATING, 0f)
|
||||||
val storeName = intent.getStringExtra(Constants.EXTRA_STORE_NAME) ?: ""
|
val storeName = intent.getStringExtra(Constants.EXTRA_STORE_NAME) ?: ""
|
||||||
val chatRoomId = intent.getIntExtra(Constants.EXTRA_CHAT_ROOM_ID, 0)
|
val chatRoomId = intent.getIntExtra(Constants.EXTRA_CHAT_ROOM_ID, 0)
|
||||||
|
val storeImg = intent.getStringExtra(Constants.EXTRA_STORE_IMAGE) ?: ""
|
||||||
|
|
||||||
// Check if user is logged in
|
// Check if user is logged in
|
||||||
val token = sessionManager.getToken()
|
val token = sessionManager.getToken()
|
||||||
@ -137,6 +138,19 @@ class ChatActivity : AppCompatActivity() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// Set chat parameters to ViewModel
|
||||||
viewModel.setChatParameters(
|
viewModel.setChatParameters(
|
||||||
storeId = storeId,
|
storeId = storeId,
|
||||||
@ -227,6 +241,7 @@ class ChatActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Observe state changes using LiveData
|
// Observe state changes using LiveData
|
||||||
viewModel.state.observe(this, Observer { state ->
|
viewModel.state.observe(this, Observer { state ->
|
||||||
// Update messages
|
// Update messages
|
||||||
@ -244,6 +259,7 @@ class ChatActivity : AppCompatActivity() {
|
|||||||
binding.ratingBar.rating = state.productRating
|
binding.ratingBar.rating = state.productRating
|
||||||
binding.tvRating.text = state.productRating.toString()
|
binding.tvRating.text = state.productRating.toString()
|
||||||
binding.tvSellerName.text = state.storeName
|
binding.tvSellerName.text = state.storeName
|
||||||
|
binding.tvStoreName.text=state.storeName
|
||||||
|
|
||||||
// Load product image
|
// Load product image
|
||||||
if (!state.productImageUrl.isNullOrEmpty()) {
|
if (!state.productImageUrl.isNullOrEmpty()) {
|
||||||
@ -270,6 +286,7 @@ class ChatActivity : AppCompatActivity() {
|
|||||||
binding.editTextMessage.hint = getString(R.string.write_message)
|
binding.editTextMessage.hint = getString(R.string.write_message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Show typing indicator
|
// Show typing indicator
|
||||||
binding.tvTypingIndicator.visibility =
|
binding.tvTypingIndicator.visibility =
|
||||||
if (state.isOtherUserTyping) View.VISIBLE else View.GONE
|
if (state.isOtherUserTyping) View.VISIBLE else View.GONE
|
||||||
@ -467,7 +484,8 @@ class ChatActivity : AppCompatActivity() {
|
|||||||
productImage: String? = null,
|
productImage: String? = null,
|
||||||
productRating: String? = null,
|
productRating: String? = null,
|
||||||
storeName: String? = null,
|
storeName: String? = null,
|
||||||
chatRoomId: Int = 0
|
chatRoomId: Int = 0,
|
||||||
|
storeImage: String? = null
|
||||||
) {
|
) {
|
||||||
val intent = Intent(context, ChatActivity::class.java).apply {
|
val intent = Intent(context, ChatActivity::class.java).apply {
|
||||||
putExtra(Constants.EXTRA_STORE_ID, storeId)
|
putExtra(Constants.EXTRA_STORE_ID, storeId)
|
||||||
@ -475,6 +493,7 @@ class ChatActivity : AppCompatActivity() {
|
|||||||
putExtra(Constants.EXTRA_PRODUCT_NAME, productName)
|
putExtra(Constants.EXTRA_PRODUCT_NAME, productName)
|
||||||
putExtra(Constants.EXTRA_PRODUCT_PRICE, productPrice)
|
putExtra(Constants.EXTRA_PRODUCT_PRICE, productPrice)
|
||||||
putExtra(Constants.EXTRA_PRODUCT_IMAGE, productImage)
|
putExtra(Constants.EXTRA_PRODUCT_IMAGE, productImage)
|
||||||
|
putExtra(Constants.EXTRA_STORE_IMAGE, storeImage)
|
||||||
|
|
||||||
// Convert productRating string to float if provided
|
// Convert productRating string to float if provided
|
||||||
if (productRating != null) {
|
if (productRating != 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<out String>,
|
|
||||||
// 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
|
|
||||||
// }
|
|
||||||
//}
|
|
@ -21,6 +21,7 @@ class ChatListFragment : Fragment() {
|
|||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
private lateinit var socketService: SocketIOService
|
private lateinit var socketService: SocketIOService
|
||||||
private lateinit var sessionManager: SessionManager
|
private lateinit var sessionManager: SessionManager
|
||||||
|
|
||||||
private val viewModel: com.alya.ecommerce_serang.ui.chat.ChatViewModel by viewModels {
|
private val viewModel: com.alya.ecommerce_serang.ui.chat.ChatViewModel by viewModels {
|
||||||
BaseViewModelFactory {
|
BaseViewModelFactory {
|
||||||
val apiService = ApiConfig.getApiService(sessionManager)
|
val apiService = ApiConfig.getApiService(sessionManager)
|
||||||
@ -65,7 +66,8 @@ class ChatListFragment : Fragment() {
|
|||||||
productImage = null,
|
productImage = null,
|
||||||
productRating = null,
|
productRating = null,
|
||||||
storeName = chatItem.storeName,
|
storeName = chatItem.storeName,
|
||||||
chatRoomId = chatItem.chatRoomId
|
chatRoomId = chatItem.chatRoomId,
|
||||||
|
storeImage = chatItem.storeImage
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
binding.chatListRecyclerView.adapter = adapter
|
binding.chatListRecyclerView.adapter = adapter
|
||||||
@ -85,4 +87,8 @@ class ChatListFragment : Fragment() {
|
|||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
@ -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.ChatItem
|
||||||
import com.alya.ecommerce_serang.data.api.response.chat.ChatItemList
|
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.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.ChatRepository
|
||||||
import com.alya.ecommerce_serang.data.repository.Result
|
import com.alya.ecommerce_serang.data.repository.Result
|
||||||
import com.alya.ecommerce_serang.utils.Constants
|
import com.alya.ecommerce_serang.utils.Constants
|
||||||
@ -23,6 +24,8 @@ import javax.inject.Inject
|
|||||||
class ChatViewModel @Inject constructor(
|
class ChatViewModel @Inject constructor(
|
||||||
private val chatRepository: ChatRepository,
|
private val chatRepository: ChatRepository,
|
||||||
private val socketService: SocketIOService,
|
private val socketService: SocketIOService,
|
||||||
|
|
||||||
|
|
||||||
private val sessionManager: SessionManager
|
private val sessionManager: SessionManager
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
@ -38,6 +41,9 @@ class ChatViewModel @Inject constructor(
|
|||||||
private val _chatList = MutableLiveData<Result<List<ChatItemList>>>()
|
private val _chatList = MutableLiveData<Result<List<ChatItemList>>>()
|
||||||
val chatList: LiveData<Result<List<ChatItemList>>> = _chatList
|
val chatList: LiveData<Result<List<ChatItemList>>> = _chatList
|
||||||
|
|
||||||
|
private val _storeDetail = MutableLiveData<Result<StoreProduct?>>()
|
||||||
|
val storeDetail : LiveData<Result<StoreProduct?>> get() = _storeDetail
|
||||||
|
|
||||||
// Store and product parameters
|
// Store and product parameters
|
||||||
private var storeId: Int = 0
|
private var storeId: Int = 0
|
||||||
private var productId: Int? = 0
|
private var productId: Int? = 0
|
||||||
|
@ -154,6 +154,7 @@ class OrderHistoryAdapter(
|
|||||||
text = itemView.context.getString(R.string.canceled_order_btn)
|
text = itemView.context.getString(R.string.canceled_order_btn)
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
showCancelOrderBottomSheet(order.orderId)
|
showCancelOrderBottomSheet(order.orderId)
|
||||||
|
viewModel.refreshOrders()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
deadlineDate.apply {
|
deadlineDate.apply {
|
||||||
@ -175,6 +176,7 @@ class OrderHistoryAdapter(
|
|||||||
text = itemView.context.getString(R.string.canceled_order_btn)
|
text = itemView.context.getString(R.string.canceled_order_btn)
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
showCancelOrderBottomSheet(order.orderId)
|
showCancelOrderBottomSheet(order.orderId)
|
||||||
|
viewModel.refreshOrders()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,6 +213,7 @@ class OrderHistoryAdapter(
|
|||||||
text = itemView.context.getString(R.string.canceled_order_btn)
|
text = itemView.context.getString(R.string.canceled_order_btn)
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
showCancelOrderDialog(order.orderId.toString())
|
showCancelOrderDialog(order.orderId.toString())
|
||||||
|
viewModel.refreshOrders()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -229,6 +232,7 @@ class OrderHistoryAdapter(
|
|||||||
text = itemView.context.getString(R.string.claim_complaint)
|
text = itemView.context.getString(R.string.claim_complaint)
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
showCancelOrderDialog(order.orderId.toString())
|
showCancelOrderDialog(order.orderId.toString())
|
||||||
|
viewModel.refreshOrders()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
btnRight.apply {
|
btnRight.apply {
|
||||||
@ -237,6 +241,7 @@ class OrderHistoryAdapter(
|
|||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
// Handle click event
|
// Handle click event
|
||||||
viewModel.confirmOrderCompleted(order.orderId, "completed")
|
viewModel.confirmOrderCompleted(order.orderId, "completed")
|
||||||
|
viewModel.refreshOrders()
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -245,16 +250,6 @@ class OrderHistoryAdapter(
|
|||||||
text = formatShipmentDate(order.updatedAt, order.etd ?: "0")
|
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" -> {
|
"completed" -> {
|
||||||
statusOrder.apply {
|
statusOrder.apply {
|
||||||
visibility = View.VISIBLE
|
visibility = View.VISIBLE
|
||||||
@ -269,6 +264,7 @@ class OrderHistoryAdapter(
|
|||||||
text = itemView.context.getString(R.string.add_review)
|
text = itemView.context.getString(R.string.add_review)
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
addReviewProduct(order)
|
addReviewProduct(order)
|
||||||
|
viewModel.refreshOrders()
|
||||||
// Handle click event
|
// Handle click event
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,11 +47,9 @@ class OrderHistoryFragment : Fragment() {
|
|||||||
1 -> getString(R.string.pending_orders)
|
1 -> getString(R.string.pending_orders)
|
||||||
2 -> getString(R.string.unpaid_orders)
|
2 -> getString(R.string.unpaid_orders)
|
||||||
3 -> getString(R.string.processed_orders)
|
3 -> getString(R.string.processed_orders)
|
||||||
4 -> getString(R.string.paid_orders)
|
4 -> getString(R.string.shipped_orders)
|
||||||
5 -> getString(R.string.shipped_orders)
|
5 -> getString(R.string.completed_orders)
|
||||||
6 -> getString(R.string.delivered_orders)
|
6 -> getString(R.string.canceled_orders)
|
||||||
7 -> getString(R.string.completed_orders)
|
|
||||||
8 -> getString(R.string.canceled_orders)
|
|
||||||
else -> "Tab $position"
|
else -> "Tab $position"
|
||||||
}
|
}
|
||||||
}.attach()
|
}.attach()
|
||||||
|
@ -14,9 +14,7 @@ class OrderViewPagerAdapter(
|
|||||||
"pending", // Menunggu Tagihan
|
"pending", // Menunggu Tagihan
|
||||||
"unpaid", // Belum Dibayar
|
"unpaid", // Belum Dibayar
|
||||||
"processed", // Diproses
|
"processed", // Diproses
|
||||||
"paid", // Dibayar
|
|
||||||
"shipped", // Dikirim
|
"shipped", // Dikirim
|
||||||
"delivered", // Diterima
|
|
||||||
"completed", // Selesai
|
"completed", // Selesai
|
||||||
"canceled" // Dibatalkan
|
"canceled" // Dibatalkan
|
||||||
)
|
)
|
||||||
|
@ -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.data.repository.OrderRepository
|
||||||
import com.alya.ecommerce_serang.databinding.ActivityDetailOrderStatusBinding
|
import com.alya.ecommerce_serang.databinding.ActivityDetailOrderStatusBinding
|
||||||
import com.alya.ecommerce_serang.ui.order.detail.PaymentActivity
|
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.order.review.CreateReviewActivity
|
||||||
import com.alya.ecommerce_serang.ui.product.ReviewProductActivity
|
import com.alya.ecommerce_serang.ui.product.ReviewProductActivity
|
||||||
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
||||||
@ -50,6 +51,7 @@ class DetailOrderStatusActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private lateinit var binding: ActivityDetailOrderStatusBinding
|
private lateinit var binding: ActivityDetailOrderStatusBinding
|
||||||
private lateinit var sessionManager: SessionManager
|
private lateinit var sessionManager: SessionManager
|
||||||
|
|
||||||
private var orderId: Int = -1
|
private var orderId: Int = -1
|
||||||
private var orderStatus: String = ""
|
private var orderStatus: String = ""
|
||||||
private val orders = mutableListOf<OrdersItem>()
|
private val orders = mutableListOf<OrdersItem>()
|
||||||
@ -181,9 +183,9 @@ class DetailOrderStatusActivity : AppCompatActivity() {
|
|||||||
setupProductsRecyclerView(orders.orderItems)
|
setupProductsRecyclerView(orders.orderItems)
|
||||||
|
|
||||||
// Set payment method
|
// 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
|
// Set subtotal, shipping cost, and total
|
||||||
val subtotal = orders.totalAmount?.toIntOrNull()?.minus(orders.shipmentPrice.toIntOrNull() ?: 0) ?: 0
|
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'")
|
Log.d(TAG, "adjustButtonsBasedOnStatus: Status header set to '$statusText'")
|
||||||
|
|
||||||
when (status) {
|
when (status) {
|
||||||
"pending", "unpaid" -> {
|
"pending"->{
|
||||||
Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for pending/unpaid order")
|
binding.tvStatusHeader.text = "Menunggu Tagihan"
|
||||||
|
|
||||||
// Show status note
|
|
||||||
binding.tvStatusNote.visibility = View.VISIBLE
|
binding.tvStatusNote.visibility = View.VISIBLE
|
||||||
binding.tvStatusNote.text = "Pesanan ini harus dibayar sebelum ${formatDatePay(orders.updatedAt)}"
|
binding.tvStatusNote.text = "Pesanan ini harus dibayar sebelum ${formatDatePay(orders.updatedAt)}"
|
||||||
|
|
||||||
@ -250,7 +250,27 @@ class DetailOrderStatusActivity : AppCompatActivity() {
|
|||||||
text = "Batalkan Pesanan"
|
text = "Batalkan Pesanan"
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
Log.d(TAG, "Cancel Order button clicked")
|
Log.d(TAG, "Cancel Order button clicked")
|
||||||
showCancelOrderDialog(orders.orderId.toString())
|
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" -> {
|
"processed" -> {
|
||||||
Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for processed order")
|
Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for processed order")
|
||||||
|
|
||||||
|
binding.tvStatusHeader.text = "Sedang Diproses"
|
||||||
binding.tvStatusNote.visibility = View.VISIBLE
|
binding.tvStatusNote.visibility = View.VISIBLE
|
||||||
binding.tvStatusNote.text = "Penjual sedang memproses pesanan Anda"
|
binding.tvStatusNote.text = "Penjual sedang memproses pesanan Anda"
|
||||||
|
|
||||||
@ -279,13 +300,19 @@ class DetailOrderStatusActivity : AppCompatActivity() {
|
|||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
Log.d(TAG, "Cancel Order button clicked for processed order")
|
Log.d(TAG, "Cancel Order button clicked for processed order")
|
||||||
showCancelOrderDialog(orders.orderId.toString())
|
showCancelOrderDialog(orders.orderId.toString())
|
||||||
|
viewModel.getOrderDetails(orders.orderId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.btnPrimary.apply {
|
||||||
|
visibility = View.GONE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"shipped" -> {
|
"shipped" -> {
|
||||||
Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for shipped order")
|
Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for shipped order")
|
||||||
|
|
||||||
|
binding.tvStatusHeader.text = "Sudah Dikirim"
|
||||||
binding.tvStatusNote.visibility = View.VISIBLE
|
binding.tvStatusNote.visibility = View.VISIBLE
|
||||||
binding.tvStatusNote.text = "Pesanan Anda sedang dalam perjalanan. Akan sampai sekitar ${formatShipmentDate(orders.updatedAt, orders.etd ?: "0")}"
|
binding.tvStatusNote.text = "Pesanan Anda sedang dalam perjalanan. Akan sampai sekitar ${formatShipmentDate(orders.updatedAt, orders.etd ?: "0")}"
|
||||||
|
|
||||||
@ -294,7 +321,8 @@ class DetailOrderStatusActivity : AppCompatActivity() {
|
|||||||
text = "Ajukan Komplain"
|
text = "Ajukan Komplain"
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
Log.d(TAG, "Complaint button clicked")
|
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")
|
Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for delivered/completed order")
|
||||||
|
|
||||||
binding.tvStatusNote.visibility = View.VISIBLE
|
binding.tvStatusHeader.text = "Pesanan Selesai"
|
||||||
binding.tvStatusNote.text = "Pesanan telah selesai"
|
binding.tvStatusNote.visibility = View.GONE
|
||||||
|
|
||||||
binding.btnPrimary.apply {
|
binding.btnPrimary.apply {
|
||||||
visibility = View.VISIBLE
|
visibility = View.VISIBLE
|
||||||
@ -326,15 +354,27 @@ class DetailOrderStatusActivity : AppCompatActivity() {
|
|||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
Log.d(TAG, "Review button clicked")
|
Log.d(TAG, "Review button clicked")
|
||||||
addReviewForOrder(orders)
|
addReviewForOrder(orders)
|
||||||
|
viewModel.getOrderDetails(orders.orderId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
binding.btnSecondary.apply {
|
||||||
|
visibility = View.GONE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"canceled" -> {
|
"canceled" -> {
|
||||||
Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for canceled order")
|
Log.d(TAG, "adjustButtonsBasedOnStatus: Setting up UI for canceled order")
|
||||||
|
|
||||||
|
binding.tvStatusHeader.text = "Pesanan Selesai"
|
||||||
binding.tvStatusNote.visibility = View.VISIBLE
|
binding.tvStatusNote.visibility = View.VISIBLE
|
||||||
binding.tvStatusNote.text = "Pesanan dibatalkan: ${orders.cancelReason ?: "Alasan tidak diberikan"}"
|
binding.tvStatusNote.text = "Pesanan dibatalkan: ${orders.cancelReason ?: "Alasan tidak diberikan"}"
|
||||||
|
|
||||||
|
binding.btnSecondary.apply {
|
||||||
|
visibility = View.GONE
|
||||||
|
}
|
||||||
|
binding.btnPrimary.apply {
|
||||||
|
visibility = View.GONE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -530,6 +570,22 @@ class DetailOrderStatusActivity : AppCompatActivity() {
|
|||||||
dialog.show()
|
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 {
|
private fun formatDate(dateString: String): String {
|
||||||
Log.d(TAG, "formatDate: Formatting date: $dateString")
|
Log.d(TAG, "formatDate: Formatting date: $dateString")
|
||||||
|
|
||||||
|
@ -414,7 +414,8 @@ class DetailProductActivity : AppCompatActivity() {
|
|||||||
productImage = productDetail.image,
|
productImage = productDetail.image,
|
||||||
productRating = productDetail.rating,
|
productRating = productDetail.rating,
|
||||||
storeName = storeDetail.data.storeName,
|
storeName = storeDetail.data.storeName,
|
||||||
chatRoomId = 0
|
chatRoomId = 0,
|
||||||
|
storeImage = storeDetail.data.storeImage
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ object Constants {
|
|||||||
const val EXTRA_PRODUCT_PRICE = "product_price"
|
const val EXTRA_PRODUCT_PRICE = "product_price"
|
||||||
const val EXTRA_PRODUCT_IMAGE = "product_image"
|
const val EXTRA_PRODUCT_IMAGE = "product_image"
|
||||||
const val EXTRA_PRODUCT_RATING = "product_rating"
|
const val EXTRA_PRODUCT_RATING = "product_rating"
|
||||||
|
const val EXTRA_STORE_IMAGE = "store_image"
|
||||||
|
|
||||||
// Request codes
|
// Request codes
|
||||||
const val REQUEST_IMAGE_PICK = 1001
|
const val REQUEST_IMAGE_PICK = 1001
|
||||||
|
@ -60,6 +60,8 @@ class ProfileViewModel(private val userRepository: UserRepository) : ViewModel()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun editProfileDirect(
|
fun editProfileDirect(
|
||||||
context: Context,
|
context: Context,
|
||||||
username: String,
|
username: String,
|
||||||
|
@ -6,7 +6,9 @@ import androidx.lifecycle.MutableLiveData
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.alya.ecommerce_serang.data.api.dto.RegisterRequest
|
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.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.Result
|
||||||
import com.alya.ecommerce_serang.data.repository.UserRepository
|
import com.alya.ecommerce_serang.data.repository.UserRepository
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -21,6 +23,9 @@ class RegisterViewModel(private val repository: UserRepository) : ViewModel() {
|
|||||||
private val _otpState = MutableLiveData<Result<Unit>>()
|
private val _otpState = MutableLiveData<Result<Unit>>()
|
||||||
val otpState: LiveData<Result<Unit>> = _otpState
|
val otpState: LiveData<Result<Unit>> = _otpState
|
||||||
|
|
||||||
|
private val _checkValue = MutableLiveData<Result<Boolean>>()
|
||||||
|
val checkValue: LiveData<Result<Boolean>> = _checkValue
|
||||||
|
|
||||||
// MutableLiveData to store messages from API responses
|
// MutableLiveData to store messages from API responses
|
||||||
private val _message = MutableLiveData<String>()
|
private val _message = MutableLiveData<String>()
|
||||||
val message: LiveData<String> = _message
|
val message: LiveData<String> = _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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -49,7 +49,7 @@
|
|||||||
android:text="@string/fragment_home_categories"
|
android:text="@string/fragment_home_categories"
|
||||||
android:textColor="@color/blue_500"
|
android:textColor="@color/blue_500"
|
||||||
android:fontFamily="@font/dmsans_bold"
|
android:fontFamily="@font/dmsans_bold"
|
||||||
android:textSize="22sp"
|
android:textSize="18sp"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/banners" />
|
app:layout_constraintTop_toBottomOf="@id/banners" />
|
||||||
|
|
||||||
@ -89,7 +89,7 @@
|
|||||||
android:text="@string/sold_product_text"
|
android:text="@string/sold_product_text"
|
||||||
android:textColor="@color/blue_500"
|
android:textColor="@color/blue_500"
|
||||||
android:fontFamily="@font/dmsans_bold"
|
android:fontFamily="@font/dmsans_bold"
|
||||||
android:textSize="22sp"
|
android:textSize="18sp"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/categories" />
|
app:layout_constraintTop_toBottomOf="@id/categories" />
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
@ -101,7 +101,7 @@
|
|||||||
android:text="@string/show_all"
|
android:text="@string/show_all"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textColor="@color/blue_600"
|
android:textColor="@color/blue_600"
|
||||||
android:textSize="16sp"
|
android:textSize="14sp"
|
||||||
app:layout_constraintBaseline_toBaselineOf="@id/new_products_text"
|
app:layout_constraintBaseline_toBaselineOf="@id/new_products_text"
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:src="@drawable/outline_account_circle_24"
|
android:src="@drawable/outline_account_circle_24"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
@ -7,11 +7,12 @@
|
|||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
<com.google.android.material.card.MaterialCardView
|
||||||
android:id="@+id/imageLayout"
|
android:id="@+id/imageLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="150dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
app:cardCornerRadius="14dp"
|
app:cardCornerRadius="14dp"
|
||||||
app:layout_constraintDimensionRatio="272:218"
|
app:layout_constraintDimensionRatio="272:218"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:cardElevation="0dp"
|
app:cardElevation="0dp"
|
||||||
app:strokeColor="@color/gray_1"
|
app:strokeColor="@color/gray_1"
|
||||||
app:strokeWidth="1dp">
|
app:strokeWidth="1dp">
|
||||||
@ -32,7 +33,7 @@
|
|||||||
android:text="Banana"
|
android:text="Banana"
|
||||||
android:textColor="@color/black"
|
android:textColor="@color/black"
|
||||||
android:fontFamily="@font/dmsans_medium"
|
android:fontFamily="@font/dmsans_medium"
|
||||||
android:textSize="18sp"
|
android:textSize="16sp"
|
||||||
app:layout_constraintTop_toBottomOf="@id/imageLayout" />
|
app:layout_constraintTop_toBottomOf="@id/imageLayout" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -42,7 +43,7 @@
|
|||||||
android:text="@string/item_price_txt"
|
android:text="@string/item_price_txt"
|
||||||
android:textColor="@color/black"
|
android:textColor="@color/black"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:textSize="18sp"
|
android:textSize="16sp"
|
||||||
app:layout_constraintTop_toBottomOf="@id/item_name" />
|
app:layout_constraintTop_toBottomOf="@id/item_name" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -58,7 +59,7 @@
|
|||||||
android:text="@string/rating"
|
android:text="@string/rating"
|
||||||
android:textColor="@color/black"
|
android:textColor="@color/black"
|
||||||
android:fontFamily="@font/dmsans_regular"
|
android:fontFamily="@font/dmsans_regular"
|
||||||
android:textSize="14sp"
|
android:textSize="12sp"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
app:drawableStartCompat="@drawable/baseline_star_24"
|
app:drawableStartCompat="@drawable/baseline_star_24"
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
android:backgroundTint="@color/white"
|
android:backgroundTint="@color/white"
|
||||||
android:src="@drawable/outline_notifications_24"
|
android:src="@drawable/outline_notifications_24"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_constraintDimensionRatio="1:1"
|
||||||
|
android:visibility="gone"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/search"
|
app:layout_constraintBottom_toBottomOf="@id/search"
|
||||||
app:layout_constraintEnd_toStartOf="@id/btn_cart"
|
app:layout_constraintEnd_toStartOf="@id/btn_cart"
|
||||||
app:layout_constraintTop_toTopOf="@id/search"/>
|
app:layout_constraintTop_toTopOf="@id/search"/>
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
|
|
||||||
<style name="BottomNavigationTextStyle" parent="TextAppearance.MaterialComponents.Caption">
|
<style name="BottomNavigationTextStyle" parent="TextAppearance.MaterialComponents.Caption">
|
||||||
<item name="android:textSize">14sp</item>
|
<item name="android:textSize">14sp</item>
|
||||||
<item name="fontFamily">@font/dmsans_semibold</item>
|
<item name="fontFamily">@font/dmsans_medium</item>
|
||||||
<item name="android:paddingTop">8dp</item>
|
<item name="android:paddingTop">8dp</item>
|
||||||
<item name="android:layout_marginTop">4dp</item>
|
<item name="android:layout_marginTop">4dp</item>
|
||||||
</style>
|
</style>
|
||||||
|
Reference in New Issue
Block a user