update icon, chat, balance, and count order
BIN
app/src/main/ic_launcher-playstore.png
Normal file
After Width: | Height: | Size: 27 KiB |
@ -5,6 +5,7 @@ import com.alya.ecommerce_serang.data.api.dto.Store
|
||||
import com.alya.ecommerce_serang.data.api.response.auth.ListStoreTypeResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.store.profile.StoreDataResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.store.sells.OrderListResponse
|
||||
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody
|
||||
@ -71,4 +72,90 @@ class MyStoreRepository(private val apiService: ApiService) {
|
||||
street, subdistrict, detail, postalCode, latitude, longitude, userPhone, storeType, storeimg
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun getSellList(status: String): Result<OrderListResponse> {
|
||||
return try {
|
||||
Log.d("SellsRepository", "Add Evidence : $status")
|
||||
val response = apiService.getSellList(status)
|
||||
|
||||
if (response.isSuccessful) {
|
||||
val allListSell = response.body()
|
||||
if (allListSell != null) {
|
||||
Log.d("SellsRepository", "Add Evidence successfully: ${allListSell.message}")
|
||||
Result.Success(allListSell)
|
||||
} else {
|
||||
Log.e("SellsRepository", "Response body was null")
|
||||
Result.Error(Exception("Empty response from server"))
|
||||
}
|
||||
} else {
|
||||
val errorBody = response.errorBody()?.string() ?: "Unknown error"
|
||||
Log.e("SellsRepository", "Error Add Evidence : $errorBody")
|
||||
Result.Error(Exception(errorBody))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("SellsRepository", "Exception Add Evidence ", e)
|
||||
Result.Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getBalance(): Result<com.alya.ecommerce_serang.data.api.response.store.StoreResponse> {
|
||||
return try {
|
||||
val response = apiService.getMyStoreData()
|
||||
|
||||
if (response.isSuccessful) {
|
||||
val body = response.body()
|
||||
?: return Result.Error(IllegalStateException("Response body is null"))
|
||||
|
||||
// Validate the balance field
|
||||
val balanceRaw = body.store.balance
|
||||
balanceRaw.toDoubleOrNull()
|
||||
?: return Result.Error(NumberFormatException("Invalid balance format: $balanceRaw"))
|
||||
|
||||
Result.Success(body)
|
||||
} else {
|
||||
Result.Error(
|
||||
Exception("Failed to load balance: ${response.code()} ${response.message()}")
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("MyStoreRepository", "Error fetching balance", e)
|
||||
Result.Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
// private fun fetchBalance() {
|
||||
// showLoading(true)
|
||||
// lifecycleScope.launch {
|
||||
// try {
|
||||
// val response = ApiConfig.getApiService(sessionManager).getMyStoreData()
|
||||
// if (response.isSuccessful && response.body() != null) {
|
||||
// val storeData = response.body()!!
|
||||
// val balance = storeData.store.balance
|
||||
//
|
||||
// // Format the balance
|
||||
// try {
|
||||
// val balanceValue = balance.toDouble()
|
||||
// binding.tvBalance.text = String.format("Rp%,.0f", balanceValue)
|
||||
// } catch (e: Exception) {
|
||||
// binding.tvBalance.text = "Rp$balance"
|
||||
// }
|
||||
// } else {
|
||||
// Toast.makeText(
|
||||
// this@BalanceActivity,
|
||||
// "Gagal memuat data saldo: ${response.message()}",
|
||||
// Toast.LENGTH_SHORT
|
||||
// ).show()
|
||||
// }
|
||||
// } catch (e: Exception) {
|
||||
// Log.e(TAG, "Error fetching balance", e)
|
||||
// Toast.makeText(
|
||||
// this@BalanceActivity,
|
||||
// "Error: ${e.message}",
|
||||
// Toast.LENGTH_SHORT
|
||||
// ).show()
|
||||
// } finally {
|
||||
// showLoading(false)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
@ -63,6 +63,8 @@ class ChatActivity : AppCompatActivity() {
|
||||
// For image attachment
|
||||
private var tempImageUri: Uri? = null
|
||||
|
||||
private var imageAttach = false
|
||||
|
||||
// Typing indicator handler
|
||||
private val typingHandler = android.os.Handler(android.os.Looper.getMainLooper())
|
||||
private val stopTypingRunnable = Runnable {
|
||||
@ -269,6 +271,7 @@ class ChatActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
// Options button
|
||||
binding.btnOptions.visibility = View.GONE
|
||||
binding.btnOptions.setOnClickListener {
|
||||
showOptionsMenu()
|
||||
}
|
||||
@ -281,6 +284,7 @@ class ChatActivity : AppCompatActivity() {
|
||||
// This will automatically handle product attachment if enabled
|
||||
viewModel.sendMessage(message)
|
||||
binding.editTextMessage.text.clear()
|
||||
binding.layoutAttachImage.visibility = View.GONE
|
||||
|
||||
// Instantly scroll to show new message
|
||||
binding.recyclerChat.postDelayed({
|
||||
@ -291,24 +295,33 @@ class ChatActivity : AppCompatActivity() {
|
||||
|
||||
// Attachment button
|
||||
binding.btnAttachment.setOnClickListener {
|
||||
this.currentFocus?.let { view ->
|
||||
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
|
||||
imm?.hideSoftInputFromWindow(view.windowToken, 0)
|
||||
}
|
||||
checkPermissionsAndShowImagePicker()
|
||||
}
|
||||
|
||||
binding.btnCloseChat.setOnClickListener{
|
||||
binding.layoutAttachImage.visibility = View.GONE
|
||||
imageAttach = false
|
||||
viewModel.clearSelectedImage()
|
||||
}
|
||||
|
||||
// Product card click to enable/disable product attachment
|
||||
binding.productContainer.setOnClickListener {
|
||||
toggleProductAttachment()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun toggleProductAttachment() {
|
||||
val currentState = viewModel.state.value
|
||||
if (currentState?.hasProductAttachment == true) {
|
||||
// Disable product attachment
|
||||
viewModel.disableProductAttachment()
|
||||
updateProductAttachmentUI(false)
|
||||
Toast.makeText(this, "Product attachment disabled", Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
// Enable product attachment
|
||||
viewModel.enableProductAttachment()
|
||||
updateProductAttachmentUI(true)
|
||||
Toast.makeText(this, "Product will be attached to your next message", Toast.LENGTH_SHORT).show()
|
||||
@ -405,7 +418,7 @@ class ChatActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
// Update product info
|
||||
// layout attach product
|
||||
if (!state.productName.isNullOrEmpty()) {
|
||||
binding.tvProductName.text = state.productName
|
||||
binding.tvProductPrice.text = state.productPrice
|
||||
@ -440,15 +453,11 @@ class ChatActivity : AppCompatActivity() {
|
||||
|
||||
// Update attachment hint
|
||||
if (state.hasAttachment) {
|
||||
binding.editTextMessage.hint = getString(R.string.image_attached)
|
||||
binding.layoutAttachImage.visibility = View.VISIBLE
|
||||
} else {
|
||||
binding.editTextMessage.hint = getString(R.string.write_message)
|
||||
}
|
||||
|
||||
// Show typing indicator
|
||||
binding.tvTypingIndicator.visibility =
|
||||
if (state.isOtherUserTyping) View.VISIBLE else View.GONE
|
||||
|
||||
// Show error if any
|
||||
state.error?.let { error ->
|
||||
Toast.makeText(this@ChatActivity, error, Toast.LENGTH_SHORT).show()
|
||||
@ -459,7 +468,7 @@ class ChatActivity : AppCompatActivity() {
|
||||
|
||||
private fun updateInputHint(state: ChatUiState) {
|
||||
binding.editTextMessage.hint = when {
|
||||
state.hasAttachment -> getString(R.string.image_attached)
|
||||
state.hasAttachment -> getString(R.string.write_message)
|
||||
state.hasProductAttachment -> "Type your message (product will be attached)"
|
||||
else -> getString(R.string.write_message)
|
||||
}
|
||||
@ -504,6 +513,7 @@ class ChatActivity : AppCompatActivity() {
|
||||
getString(R.string.cancel)
|
||||
)
|
||||
|
||||
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.options))
|
||||
.setItems(options) { dialog, which ->
|
||||
@ -578,7 +588,21 @@ class ChatActivity : AppCompatActivity() {
|
||||
|
||||
private fun handleSelectedImage(uri: Uri) {
|
||||
try {
|
||||
Log.d(TAG, "Processing selected image: $uri")
|
||||
Log.d(TAG, "Processing selected image: ${uri.toString()}")
|
||||
imageAttach = true
|
||||
binding.layoutAttachImage.visibility = View.VISIBLE
|
||||
val fullImageUrl = when (val img = uri.toString()) {
|
||||
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.ivAttach)
|
||||
Log.d(TAG, "Display attach image: $uri")
|
||||
|
||||
// Always use the copy-to-cache approach for reliability
|
||||
contentResolver.openInputStream(uri)?.use { inputStream ->
|
||||
@ -598,6 +622,7 @@ class ChatActivity : AppCompatActivity() {
|
||||
|
||||
Log.d(TAG, "Image processed successfully: ${outputFile.absolutePath}, size: ${outputFile.length()}")
|
||||
viewModel.setSelectedImageFile(outputFile)
|
||||
|
||||
Toast.makeText(this, "Image selected", Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
Log.e(TAG, "Failed to create image file")
|
||||
@ -681,25 +706,4 @@ class ChatActivity : AppCompatActivity() {
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if implement typing status
|
||||
// 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)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
@ -23,6 +23,28 @@ import java.util.Locale
|
||||
import java.util.TimeZone
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* ChatViewModel - Manages chat functionality for both buyers and store owners
|
||||
*
|
||||
* ARCHITECTURE OVERVIEW:
|
||||
* - Handles real-time messaging via Socket.IO
|
||||
* - Manages chat state using LiveData/MutableLiveData pattern
|
||||
* - Supports multiple message types: TEXT, IMAGE, PRODUCT
|
||||
* - Maintains separate flows for buyer and store owner chat
|
||||
*
|
||||
* KEY RESPONSIBILITIES:
|
||||
* 1. Socket connection management and real-time message handling
|
||||
* 2. Message sending/receiving with different attachment types
|
||||
* 3. Chat history loading and message status updates
|
||||
* 4. Product attachment functionality for commerce integration
|
||||
* 5. User session management and authentication
|
||||
*
|
||||
* STATE MANAGEMENT PATTERN:
|
||||
* - All UI state updates go through updateState() helper function
|
||||
* - State updates are atomic and follow immutable pattern
|
||||
* - Error states are cleared explicitly via clearError()
|
||||
*/
|
||||
|
||||
@HiltViewModel
|
||||
class ChatViewModel @Inject constructor(
|
||||
private val chatRepository: ChatRepository,
|
||||
@ -730,6 +752,19 @@ class ChatViewModel @Inject constructor(
|
||||
Log.d(TAG, "Image attachment ${if (file != null) "selected: ${file.name}" else "cleared"}")
|
||||
}
|
||||
|
||||
fun clearSelectedImage() {
|
||||
Log.d(TAG, "Clearing selected image attachment")
|
||||
|
||||
selectedImageFile?.let { file ->
|
||||
Log.d(TAG, "Clearing image file: ${file.name}")
|
||||
}
|
||||
|
||||
selectedImageFile = null
|
||||
updateState { it.copy(hasAttachment = false) }
|
||||
|
||||
Log.d(TAG, "Image attachment cleared successfully")
|
||||
}
|
||||
|
||||
// convert form chatLine api to UI chat messages
|
||||
private fun convertChatLineToUiMessage(chatLine: ChatLine): ChatUiMessage {
|
||||
val formattedTime = formatTimestamp(chatLine.createdAt)
|
||||
|
@ -7,12 +7,14 @@ import android.widget.Toast
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.alya.ecommerce_serang.BuildConfig.BASE_URL
|
||||
import com.alya.ecommerce_serang.R
|
||||
import com.alya.ecommerce_serang.data.api.dto.Store
|
||||
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
|
||||
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
|
||||
import com.alya.ecommerce_serang.data.repository.MyStoreRepository
|
||||
import com.alya.ecommerce_serang.data.repository.Result
|
||||
import com.alya.ecommerce_serang.databinding.ActivityMyStoreBinding
|
||||
import com.alya.ecommerce_serang.ui.profile.mystore.balance.BalanceActivity
|
||||
import com.alya.ecommerce_serang.ui.profile.mystore.chat.ChatListStoreActivity
|
||||
@ -24,6 +26,7 @@ import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
||||
import com.alya.ecommerce_serang.utils.SessionManager
|
||||
import com.alya.ecommerce_serang.utils.viewmodel.MyStoreViewModel
|
||||
import com.bumptech.glide.Glide
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class MyStoreActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivityMyStoreBinding
|
||||
@ -66,6 +69,9 @@ class MyStoreActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
setUpClickListeners()
|
||||
getCountOrder()
|
||||
viewModel.fetchBalance()
|
||||
fetchBalance()
|
||||
}
|
||||
|
||||
private fun myStoreProfileOverview(store: Store){
|
||||
@ -147,6 +153,46 @@ class MyStoreActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCountOrder(){
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
val allCounts = viewModel.getAllStatusCounts()
|
||||
val totalUnpaid = allCounts["unpaid"]
|
||||
val totalPaid = allCounts["paid"]
|
||||
val totalProcessed = allCounts["processed"]
|
||||
Log.d("MyStoreActivity",
|
||||
"Total orders: unpaid=$totalUnpaid, processed=$totalProcessed, paid=$totalPaid")
|
||||
|
||||
binding.tvNumPesananMasuk.text = totalUnpaid.toString()
|
||||
binding.tvNumPembayaran.text = totalPaid.toString()
|
||||
binding.tvNumPerluDikirim.text = totalProcessed.toString()
|
||||
} catch (e:Exception){
|
||||
Log.e("MyStoreActivity", "Error getting order counts: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchBalance(){
|
||||
viewModel.balanceResult.observe(this){result ->
|
||||
when (result) {
|
||||
is com.alya.ecommerce_serang.data.repository.Result.Loading ->
|
||||
null
|
||||
// binding.progressBar.isVisible = true
|
||||
is com.alya.ecommerce_serang.data.repository.Result.Success ->
|
||||
viewModel.formattedBalance.observe(this) {
|
||||
binding.tvBalance.text = it
|
||||
}
|
||||
is Result.Error -> {
|
||||
// binding.progressBar.isVisible = false
|
||||
Log.e(
|
||||
"MyStoreActivity",
|
||||
"Gagal memuat saldo: ${result.exception.localizedMessage}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val PROFILE_REQUEST_CODE = 100
|
||||
}
|
||||
|
@ -408,6 +408,10 @@ class BalanceActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun navigateTotalBalance(){
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TOP_UP_REQUEST_CODE = 101
|
||||
}
|
||||
|
@ -426,8 +426,8 @@ class ChatStoreActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
// Show typing indicator
|
||||
binding.tvTypingIndicator.visibility =
|
||||
if (state.isOtherUserTyping) View.VISIBLE else View.GONE
|
||||
// binding.tvTypingIndicator.visibility =
|
||||
// if (state.isOtherUserTyping) View.VISIBLE else View.GONE
|
||||
|
||||
// Show error if any
|
||||
state.error?.let { error ->
|
||||
@ -520,6 +520,19 @@ class ChatStoreActivity : AppCompatActivity() {
|
||||
private fun handleSelectedImage(uri: Uri) {
|
||||
try {
|
||||
Log.d(TAG, "Processing selected image: $uri")
|
||||
binding.layoutAttachImage.visibility = View.VISIBLE
|
||||
val fullImageUrl = when (val img = uri.toString()) {
|
||||
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.ivAttach)
|
||||
Log.d(TAG, "Display attach image: $uri")
|
||||
|
||||
// Always use the copy-to-cache approach for reliability
|
||||
contentResolver.openInputStream(uri)?.use { inputStream ->
|
||||
|
@ -9,6 +9,7 @@ import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.alya.ecommerce_serang.data.api.response.store.sells.OrdersItem
|
||||
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
|
||||
@ -16,12 +17,14 @@ import com.alya.ecommerce_serang.data.repository.Result
|
||||
import com.alya.ecommerce_serang.data.repository.SellsRepository
|
||||
import com.alya.ecommerce_serang.databinding.FragmentSellsListBinding
|
||||
import com.alya.ecommerce_serang.ui.order.address.ViewState
|
||||
import com.alya.ecommerce_serang.ui.profile.mystore.MyStoreActivity
|
||||
import com.alya.ecommerce_serang.ui.profile.mystore.sells.payment.DetailPaymentActivity
|
||||
import com.alya.ecommerce_serang.ui.profile.mystore.sells.shipment.DetailShipmentActivity
|
||||
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
||||
import com.alya.ecommerce_serang.utils.SessionManager
|
||||
import com.alya.ecommerce_serang.utils.viewmodel.SellsViewModel
|
||||
import com.google.gson.Gson
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class SellsListFragment : Fragment() {
|
||||
|
||||
@ -84,6 +87,7 @@ class SellsListFragment : Fragment() {
|
||||
observeSellsList()
|
||||
observePaymentConfirmation()
|
||||
loadSells()
|
||||
// getAllOrderCountsAndNavigate()
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
@ -183,6 +187,30 @@ class SellsListFragment : Fragment() {
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
private fun getAllOrderCountsAndNavigate() {
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
// Show loading if needed
|
||||
binding.progressBar.visibility = View.VISIBLE
|
||||
|
||||
val allCounts = viewModel.getAllStatusCounts()
|
||||
|
||||
binding.progressBar.visibility = View.GONE
|
||||
|
||||
val intent = Intent(requireContext(), MyStoreActivity::class.java)
|
||||
intent.putExtra("total_unpaid", allCounts["unpaid"])
|
||||
intent.putExtra("total_paid", allCounts["paid"])
|
||||
intent.putExtra("total_processed", allCounts["processed"])
|
||||
Log.d("SellsListFragment", "Total orders: unpaid=${allCounts["unpaid"]}, processed=${allCounts["processed"]}, Paid=${allCounts["paid"]}")
|
||||
|
||||
|
||||
} catch (e: Exception) {
|
||||
binding.progressBar.visibility = View.GONE
|
||||
Log.e(TAG, "Error getting order counts: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
|
@ -1,11 +1,14 @@
|
||||
package com.alya.ecommerce_serang.utils.viewmodel
|
||||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.map
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.alya.ecommerce_serang.data.api.dto.Store
|
||||
import com.alya.ecommerce_serang.data.api.response.auth.StoreTypesItem
|
||||
import com.alya.ecommerce_serang.data.api.response.store.StoreResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.store.profile.StoreDataResponse
|
||||
import com.alya.ecommerce_serang.data.repository.MyStoreRepository
|
||||
import com.alya.ecommerce_serang.data.repository.Result
|
||||
@ -13,6 +16,8 @@ import kotlinx.coroutines.launch
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody
|
||||
import java.text.NumberFormat
|
||||
import java.util.Locale
|
||||
|
||||
class MyStoreViewModel(private val repository: MyStoreRepository): ViewModel() {
|
||||
private val _myStoreProfile = MutableLiveData<Store?>()
|
||||
@ -30,6 +35,9 @@ class MyStoreViewModel(private val repository: MyStoreRepository): ViewModel() {
|
||||
private val _errorMessage = MutableLiveData<String>()
|
||||
val errorMessage : LiveData<String> = _errorMessage
|
||||
|
||||
private val _balanceResult = MutableLiveData<Result<StoreResponse>>()
|
||||
val balanceResult: LiveData<Result<StoreResponse>> get() = _balanceResult
|
||||
|
||||
fun loadMyStore(){
|
||||
viewModelScope.launch {
|
||||
when (val result = repository.fetchMyStoreProfile()){
|
||||
@ -100,6 +108,56 @@ class MyStoreViewModel(private val repository: MyStoreRepository): ViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getTotalOrdersByStatus(status: String): Int {
|
||||
return try {
|
||||
when (val result = repository.getSellList(status)) {
|
||||
is Result.Success -> {
|
||||
// Access the orders list from the response
|
||||
result.data.orders.size ?: 0
|
||||
}
|
||||
is Result.Error -> {
|
||||
Log.e("SellsViewModel", "Error getting orders count: ${result.exception.message}")
|
||||
0
|
||||
}
|
||||
is Result.Loading -> 0
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("SellsViewModel", "Exception getting orders count", e)
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
//count the order
|
||||
suspend fun getAllStatusCounts(): Map<String, Int> {
|
||||
val statuses = listOf( "unpaid", "paid", "processed")
|
||||
val counts = mutableMapOf<String, Int>()
|
||||
|
||||
statuses.forEach { status ->
|
||||
counts[status] = getTotalOrdersByStatus(status)
|
||||
Log.d("SellsViewModel", "Status: $status, countOrder=${counts[status]}")
|
||||
}
|
||||
|
||||
return counts
|
||||
}
|
||||
|
||||
val formattedBalance: LiveData<String> = balanceResult.map { result ->
|
||||
when (result) {
|
||||
is Result.Success -> {
|
||||
val raw = result.data.store.balance.toDouble()
|
||||
NumberFormat.getCurrencyInstance(Locale("in", "ID")).format(raw)
|
||||
}
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
/** Trigger the network call */
|
||||
fun fetchBalance() {
|
||||
viewModelScope.launch {
|
||||
_balanceResult.value = Result.Loading
|
||||
_balanceResult.value = repository.getBalance()
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.toRequestBody(): RequestBody =
|
||||
RequestBody.create("text/plain".toMediaTypeOrNull(), this)
|
||||
}
|
@ -146,6 +146,38 @@ class SellsViewModel(private val repository: SellsRepository) : ViewModel() {
|
||||
|
||||
Log.d(TAG, "========== getSellList method completed ==========")
|
||||
}
|
||||
//get total order each status
|
||||
suspend fun getTotalOrdersByStatus(status: String): Int {
|
||||
return try {
|
||||
when (val result = repository.getSellList(status)) {
|
||||
is Result.Success -> {
|
||||
// Access the orders list from the response
|
||||
result.data.orders.size ?: 0
|
||||
}
|
||||
is Result.Error -> {
|
||||
Log.e("SellsViewModel", "Error getting orders count: ${result.exception.message}")
|
||||
0
|
||||
}
|
||||
is Result.Loading -> 0
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("SellsViewModel", "Exception getting orders count", e)
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
//count the order
|
||||
suspend fun getAllStatusCounts(): Map<String, Int> {
|
||||
val statuses = listOf( "unpaid", "paid", "processed")
|
||||
val counts = mutableMapOf<String, Int>()
|
||||
|
||||
statuses.forEach { status ->
|
||||
counts[status] = getTotalOrdersByStatus(status)
|
||||
Log.d("SellsViewModel", "Status: $status, countOrder=${counts[status]}")
|
||||
}
|
||||
|
||||
return counts
|
||||
}
|
||||
|
||||
fun getSellDetails(orderId: Int) {
|
||||
Log.d(TAG, "========== Starting getSellDetails ==========")
|
||||
|
9
app/src/main/res/drawable/ic_close_chat.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="14dp"
|
||||
android:height="14dp"
|
||||
android:viewportWidth="14"
|
||||
android:viewportHeight="14">
|
||||
<path
|
||||
android:pathData="M7,8.4L2.1,13.3C1.917,13.483 1.683,13.575 1.4,13.575C1.117,13.575 0.883,13.483 0.7,13.3C0.517,13.116 0.425,12.883 0.425,12.6C0.425,12.316 0.517,12.083 0.7,11.9L5.6,7L0.7,2.1C0.517,1.916 0.425,1.683 0.425,1.4C0.425,1.116 0.517,0.883 0.7,0.7C0.883,0.516 1.117,0.425 1.4,0.425C1.683,0.425 1.917,0.516 2.1,0.7L7,5.6L11.9,0.7C12.083,0.516 12.317,0.425 12.6,0.425C12.883,0.425 13.117,0.516 13.3,0.7C13.483,0.883 13.575,1.116 13.575,1.4C13.575,1.683 13.483,1.916 13.3,2.1L8.4,7L13.3,11.9C13.483,12.083 13.575,12.316 13.575,12.6C13.575,12.883 13.483,13.116 13.3,13.3C13.117,13.483 12.883,13.575 12.6,13.575C12.317,13.575 12.083,13.483 11.9,13.3L7,8.4Z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
@ -1,170 +1,74 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
<vector
|
||||
android:height="108dp"
|
||||
android:width="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
</vector>
|
||||
|
@ -1,30 +1,20 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
android:viewportWidth="64"
|
||||
android:viewportHeight="64">
|
||||
<group android:scaleX="0.6722222"
|
||||
android:scaleY="0.6722222"
|
||||
android:translateX="10.488889"
|
||||
android:translateY="10.488889">
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
||||
android:pathData="M0,0h64v64h-64z"
|
||||
android:fillColor="#489EC6"/>
|
||||
<path
|
||||
android:pathData="M11.868,58C10.523,58 9.399,57.538 8.497,56.614C7.594,55.69 7.144,54.537 7.146,53.155V29.074C5.912,28.14 5.009,26.915 4.438,25.399C3.867,23.883 3.854,22.266 4.4,20.548L7.245,10.924C7.635,9.7 8.264,8.74 9.131,8.044C10.001,7.348 11.075,7 12.354,7H51.536C52.813,7 53.883,7.326 54.747,7.978C55.608,8.63 56.24,9.573 56.641,10.807L59.598,20.545C60.146,22.265 60.134,23.896 59.563,25.438C58.992,26.98 58.089,28.23 56.855,29.188V53.152C56.855,54.534 56.404,55.687 55.501,56.611C54.599,57.535 53.476,57.998 52.133,58H11.868ZM38.433,28C40.311,28 41.712,27.46 42.638,26.38C43.564,25.302 43.954,24.188 43.808,23.038L41.866,10H33.465V22.6C33.465,24.074 33.957,25.342 34.939,26.404C35.922,27.468 37.084,28 38.433,28ZM25.278,28C26.849,28 28.119,27.468 29.088,26.404C30.057,25.34 30.541,24.072 30.541,22.6V10H22.138L20.19,23.269C20.071,24.201 20.468,25.222 21.38,26.332C22.292,27.442 23.594,27.998 25.278,28ZM12.263,28C13.551,28 14.647,27.55 15.55,26.65C16.452,25.75 17.014,24.627 17.234,23.281L19.067,10H12.354C11.716,10 11.209,10.144 10.833,10.432C10.457,10.72 10.176,11.153 9.991,11.731L7.292,21.205C6.812,22.781 7.017,24.308 7.906,25.786C8.795,27.264 10.247,28.002 12.263,28ZM51.738,28C53.488,28 54.886,27.3 55.931,25.9C56.978,24.5 57.237,22.935 56.709,21.205L53.864,11.617C53.676,11.039 53.395,10.625 53.019,10.375C52.642,10.125 52.137,10 51.501,10H44.933L46.767,23.281C46.987,24.627 47.549,25.75 48.451,26.65C49.354,27.55 50.449,28 51.738,28Z"
|
||||
android:fillColor="#ffffff"/>
|
||||
<path
|
||||
android:pathData="M20.382,39V30.6H23.97C24.554,30.6 25.046,30.692 25.446,30.876C25.846,31.052 26.15,31.304 26.358,31.632C26.574,31.952 26.682,32.332 26.682,32.772C26.682,33.196 26.59,33.552 26.406,33.84C26.222,34.128 25.978,34.348 25.674,34.5C25.378,34.652 25.05,34.744 24.69,34.776L24.882,34.632C25.274,34.648 25.618,34.752 25.914,34.944C26.21,35.136 26.442,35.388 26.61,35.7C26.786,36.004 26.874,36.34 26.874,36.708C26.874,37.164 26.766,37.564 26.55,37.908C26.334,38.252 26.018,38.52 25.602,38.712C25.186,38.904 24.682,39 24.09,39H20.382ZM22.182,37.536H23.79C24.19,37.536 24.498,37.448 24.714,37.272C24.938,37.088 25.05,36.824 25.05,36.48C25.05,36.136 24.934,35.868 24.702,35.676C24.478,35.484 24.166,35.388 23.766,35.388H22.182V37.536ZM22.182,34.056H23.658C24.042,34.056 24.334,33.968 24.534,33.792C24.742,33.616 24.846,33.368 24.846,33.048C24.846,32.728 24.742,32.48 24.534,32.304C24.334,32.12 24.038,32.028 23.646,32.028H22.182V34.056ZM28.163,39V32.952H29.963V39H28.163ZM29.063,32.256C28.743,32.256 28.483,32.164 28.283,31.98C28.083,31.796 27.983,31.564 27.983,31.284C27.983,30.996 28.083,30.76 28.283,30.576C28.483,30.392 28.743,30.3 29.063,30.3C29.391,30.3 29.655,30.392 29.855,30.576C30.063,30.76 30.167,30.996 30.167,31.284C30.167,31.564 30.063,31.796 29.855,31.98C29.655,32.164 29.391,32.256 29.063,32.256ZM34.069,39.144C33.501,39.144 33.009,39.056 32.593,38.88C32.186,38.696 31.861,38.448 31.622,38.136C31.389,37.824 31.257,37.472 31.226,37.08H33.014C33.046,37.216 33.102,37.34 33.181,37.452C33.27,37.556 33.386,37.64 33.529,37.704C33.681,37.76 33.849,37.788 34.034,37.788C34.234,37.788 34.394,37.764 34.514,37.716C34.641,37.66 34.737,37.588 34.801,37.5C34.866,37.412 34.897,37.32 34.897,37.224C34.897,37.072 34.849,36.956 34.754,36.876C34.666,36.796 34.534,36.732 34.357,36.684C34.181,36.628 33.97,36.576 33.722,36.528C33.433,36.464 33.146,36.392 32.857,36.312C32.577,36.224 32.326,36.116 32.102,35.988C31.885,35.86 31.709,35.696 31.573,35.496C31.445,35.288 31.382,35.036 31.382,34.74C31.382,34.38 31.482,34.056 31.681,33.768C31.882,33.472 32.169,33.24 32.546,33.072C32.922,32.896 33.377,32.808 33.914,32.808C34.674,32.808 35.27,32.976 35.701,33.312C36.133,33.648 36.389,34.1 36.47,34.668H34.79C34.742,34.508 34.641,34.388 34.489,34.308C34.338,34.22 34.146,34.176 33.914,34.176C33.65,34.176 33.45,34.22 33.313,34.308C33.178,34.396 33.11,34.512 33.11,34.656C33.11,34.752 33.153,34.84 33.242,34.92C33.338,34.992 33.473,35.056 33.65,35.112C33.826,35.168 34.042,35.224 34.298,35.28C34.785,35.384 35.206,35.496 35.557,35.616C35.917,35.736 36.197,35.912 36.397,36.144C36.597,36.368 36.694,36.696 36.686,37.128C36.694,37.52 36.59,37.868 36.374,38.172C36.166,38.476 35.866,38.716 35.473,38.892C35.082,39.06 34.613,39.144 34.069,39.144ZM40.094,39.144C39.59,39.144 39.17,39.064 38.834,38.904C38.506,38.744 38.262,38.528 38.102,38.256C37.95,37.976 37.874,37.668 37.874,37.332C37.874,36.972 37.962,36.656 38.138,36.384C38.322,36.104 38.606,35.884 38.99,35.724C39.374,35.556 39.858,35.472 40.442,35.472H41.906C41.906,35.2 41.87,34.976 41.798,34.8C41.734,34.624 41.626,34.492 41.474,34.404C41.322,34.316 41.114,34.272 40.85,34.272C40.57,34.272 40.334,34.328 40.142,34.44C39.95,34.552 39.83,34.728 39.782,34.968H38.054C38.094,34.536 38.234,34.16 38.474,33.84C38.722,33.52 39.05,33.268 39.458,33.084C39.866,32.9 40.334,32.808 40.862,32.808C41.438,32.808 41.938,32.904 42.362,33.096C42.786,33.28 43.114,33.552 43.346,33.912C43.586,34.272 43.706,34.72 43.706,35.256V39H42.206L41.99,38.124C41.902,38.276 41.798,38.416 41.678,38.544C41.558,38.664 41.418,38.772 41.258,38.868C41.098,38.956 40.922,39.024 40.73,39.072C40.538,39.12 40.326,39.144 40.094,39.144ZM40.538,37.776C40.73,37.776 40.898,37.744 41.042,37.68C41.186,37.616 41.31,37.528 41.414,37.416C41.518,37.304 41.602,37.176 41.666,37.032C41.738,36.88 41.79,36.716 41.822,36.54V36.528H40.658C40.458,36.528 40.29,36.556 40.154,36.612C40.026,36.66 39.93,36.732 39.866,36.828C39.802,36.924 39.77,37.036 39.77,37.164C39.77,37.3 39.802,37.416 39.866,37.512C39.938,37.6 40.03,37.668 40.142,37.716C40.262,37.756 40.394,37.776 40.538,37.776ZM17.132,53.144C16.5,53.144 15.924,53.02 15.404,52.772C14.892,52.516 14.484,52.136 14.18,51.632C13.884,51.128 13.736,50.492 13.736,49.724V44.6H15.536V49.736C15.536,50.112 15.596,50.432 15.716,50.696C15.844,50.96 16.028,51.16 16.268,51.296C16.516,51.424 16.812,51.488 17.156,51.488C17.508,51.488 17.804,51.424 18.044,51.296C18.292,51.16 18.48,50.96 18.608,50.696C18.736,50.432 18.8,50.112 18.8,49.736V44.6H20.6V49.724C20.6,50.492 20.44,51.128 20.12,51.632C19.808,52.136 19.388,52.516 18.86,52.772C18.34,53.02 17.764,53.144 17.132,53.144ZM22.128,53V44.6H24.288L26.736,49.652L29.16,44.6H31.308V53H29.508V47.636L27.444,51.824H26.004L23.928,47.636V53H22.128ZM32.921,53V44.6H34.721V47.78L37.625,44.6H39.833L36.749,47.924L39.941,53H37.733L35.465,49.316L34.721,50.12V53H32.921ZM41.007,53V44.6H43.167L45.615,49.652L48.039,44.6H50.187V53H48.387V47.636L46.323,51.824H44.883L42.807,47.636V53H41.007Z"
|
||||
android:fillColor="#489EC6"/>
|
||||
</group>
|
||||
</vector>
|
||||
|
9
app/src/main/res/drawable/ic_sent.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="19"
|
||||
android:viewportHeight="16">
|
||||
<path
|
||||
android:pathData="M0,16V10L8,8L0,6V0L19,8L0,16Z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
@ -54,19 +54,9 @@
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintStart_toEndOf="@+id/imgProfile"
|
||||
app:layout_constraintTop_toTopOf="@+id/imgProfile"
|
||||
app:layout_constraintEnd_toStartOf="@+id/btnOptions" />
|
||||
app:layout_constraintEnd_toStartOf="@+id/btnOptions"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
<!-- <TextView-->
|
||||
<!-- android:id="@+id/tvLastActive"-->
|
||||
<!-- android:layout_width="0dp"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_marginStart="8dp"-->
|
||||
<!-- android:text="Aktif 3 jam lalu"-->
|
||||
<!-- android:textColor="#888888"-->
|
||||
<!-- android:textSize="12sp"-->
|
||||
<!-- app:layout_constraintStart_toEndOf="@+id/imgProfile"-->
|
||||
<!-- app:layout_constraintTop_toBottomOf="@+id/tvStoreName"-->
|
||||
<!-- app:layout_constraintEnd_toEndOf="@+id/tvStoreName" />-->
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnOptions"
|
||||
@ -178,22 +168,47 @@
|
||||
android:clipToPadding="false"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/tvTypingIndicator"
|
||||
app:layout_constraintBottom_toTopOf="@+id/layoutChatInput"
|
||||
app:layout_constraintTop_toBottomOf="@+id/cardProduct" />
|
||||
|
||||
<!-- Typing indicator -->
|
||||
<TextView
|
||||
android:id="@+id/tvTypingIndicator"
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/layoutAttachImage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="4dp"
|
||||
android:text="User is typing..."
|
||||
android:textColor="#666666"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="italic"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toTopOf="@+id/layoutChatInput"
|
||||
tools:visibility="visible" />
|
||||
android:padding="4dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/layoutChatInput"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="4dp">
|
||||
<ImageView
|
||||
android:id="@+id/iv_attach"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="150dp"
|
||||
android:clipToOutline="true"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginVertical="8dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
/>
|
||||
<ImageButton
|
||||
android:id="@+id/btn_close_chat"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:backgroundTint="@android:color/transparent"
|
||||
android:layout_marginEnd="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:src="@drawable/ic_close_chat"
|
||||
/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- Chat input area -->
|
||||
<LinearLayout
|
||||
@ -239,7 +254,7 @@
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="Send"
|
||||
android:src="@drawable/baseline_attach_file_24" />
|
||||
android:src="@drawable/ic_sent" />
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 982 B After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 11 KiB |
@ -1,5 +1,5 @@
|
||||
<resources>
|
||||
<string name="app_name">ecommerce_serang</string>
|
||||
<string name="app_name">Bisa UMKM</string>
|
||||
|
||||
|
||||
<!--Placeholder-->
|
||||
|