mirror of
https://github.com/shaulascr/ecommerce_serang.git
synced 2025-08-10 09:22:21 +00:00
add history and evidence
This commit is contained in:
@ -19,6 +19,12 @@
|
||||
android:theme="@style/Theme.Ecommerce_serang"
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".ui.order.history.HistoryActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".ui.order.detail.PaymentActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".data.api.response.cart.CartActivity"
|
||||
android:exported="false" />
|
||||
|
@ -0,0 +1,15 @@
|
||||
package com.alya.ecommerce_serang.data.api.dto
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import retrofit2.http.Multipart
|
||||
|
||||
data class AddEvidenceRequest (
|
||||
@SerializedName("orer_id")
|
||||
val orderId : Int,
|
||||
|
||||
@SerializedName("amount")
|
||||
val amount : String,
|
||||
|
||||
@SerializedName("evidence")
|
||||
val evidence: Multipart
|
||||
)
|
@ -0,0 +1,33 @@
|
||||
package com.alya.ecommerce_serang.data.api.response.order
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class AddEvidenceResponse(
|
||||
|
||||
@field:SerializedName("evidence")
|
||||
val evidence: Evidence,
|
||||
|
||||
@field:SerializedName("message")
|
||||
val message: String
|
||||
)
|
||||
|
||||
data class Evidence(
|
||||
|
||||
@field:SerializedName("amount")
|
||||
val amount: String,
|
||||
|
||||
@field:SerializedName("evidence")
|
||||
val evidence: String,
|
||||
|
||||
@field:SerializedName("uploaded_at")
|
||||
val uploadedAt: String,
|
||||
|
||||
@field:SerializedName("id")
|
||||
val id: Int,
|
||||
|
||||
@field:SerializedName("order_id")
|
||||
val orderId: Int,
|
||||
|
||||
@field:SerializedName("status")
|
||||
val status: String
|
||||
)
|
@ -14,22 +14,22 @@ data class OrderDetailResponse(
|
||||
data class Orders(
|
||||
|
||||
@field:SerializedName("receipt_num")
|
||||
val receiptNum: String,
|
||||
val receiptNum: String? = null,
|
||||
|
||||
@field:SerializedName("payment_upload_at")
|
||||
val paymentUploadAt: String,
|
||||
val paymentUploadAt: String? = null,
|
||||
|
||||
@field:SerializedName("latitude")
|
||||
val latitude: String,
|
||||
|
||||
@field:SerializedName("pay_info_name")
|
||||
val payInfoName: String,
|
||||
val payInfoName: String? = null,
|
||||
|
||||
@field:SerializedName("created_at")
|
||||
val createdAt: String,
|
||||
|
||||
@field:SerializedName("voucher_code")
|
||||
val voucherCode: Any,
|
||||
val voucherCode: String? = null,
|
||||
|
||||
@field:SerializedName("updated_at")
|
||||
val updatedAt: String,
|
||||
@ -41,10 +41,10 @@ data class Orders(
|
||||
val street: String,
|
||||
|
||||
@field:SerializedName("cancel_date")
|
||||
val cancelDate: String,
|
||||
val cancelDate: String? = null,
|
||||
|
||||
@field:SerializedName("payment_evidence")
|
||||
val paymentEvidence: String,
|
||||
val paymentEvidence: String? = null,
|
||||
|
||||
@field:SerializedName("longitude")
|
||||
val longitude: String,
|
||||
@ -53,34 +53,34 @@ data class Orders(
|
||||
val shipmentStatus: String,
|
||||
|
||||
@field:SerializedName("order_items")
|
||||
val orderItems: List<OrderItemsItem>,
|
||||
val orderItems: List<OrderListItemsItem>,
|
||||
|
||||
@field:SerializedName("auto_completed_at")
|
||||
val autoCompletedAt: String,
|
||||
val autoCompletedAt: String? = null,
|
||||
|
||||
@field:SerializedName("is_store_location")
|
||||
val isStoreLocation: Boolean,
|
||||
val isStoreLocation: Boolean? = null,
|
||||
|
||||
@field:SerializedName("qris_image")
|
||||
val qrisImage: String,
|
||||
val qrisImage: String? = null,
|
||||
|
||||
@field:SerializedName("voucher_name")
|
||||
val voucherName: Any,
|
||||
val voucherName: String? = null,
|
||||
|
||||
@field:SerializedName("payment_status")
|
||||
val paymentStatus: String,
|
||||
val paymentStatus: String? = null,
|
||||
|
||||
@field:SerializedName("address_id")
|
||||
val addressId: Int,
|
||||
|
||||
@field:SerializedName("payment_amount")
|
||||
val paymentAmount: String,
|
||||
val paymentAmount: String? = null,
|
||||
|
||||
@field:SerializedName("cancel_reason")
|
||||
val cancelReason: String,
|
||||
val cancelReason: String? = null,
|
||||
|
||||
@field:SerializedName("total_amount")
|
||||
val totalAmount: String,
|
||||
val totalAmount: String? = null,
|
||||
|
||||
@field:SerializedName("user_id")
|
||||
val userId: Int,
|
||||
@ -98,16 +98,16 @@ data class Orders(
|
||||
val service: String,
|
||||
|
||||
@field:SerializedName("pay_info_num")
|
||||
val payInfoNum: String,
|
||||
val payInfoNum: String? = null,
|
||||
|
||||
@field:SerializedName("shipment_price")
|
||||
val shipmentPrice: String,
|
||||
|
||||
@field:SerializedName("voucher_id")
|
||||
val voucherId: Any,
|
||||
val voucherId: Int? = null,
|
||||
|
||||
@field:SerializedName("payment_info_id")
|
||||
val paymentInfoId: Int,
|
||||
val paymentInfoId: Int? = null,
|
||||
|
||||
@field:SerializedName("detail")
|
||||
val detail: String,
|
||||
@ -122,13 +122,13 @@ data class Orders(
|
||||
val cityId: Int
|
||||
)
|
||||
|
||||
data class OrderItemsItem(
|
||||
data class OrderListItemsItem(
|
||||
|
||||
@field:SerializedName("order_item_id")
|
||||
val orderItemId: Int,
|
||||
|
||||
@field:SerializedName("review_id")
|
||||
val reviewId: Int,
|
||||
val reviewId: Int? = null,
|
||||
|
||||
@field:SerializedName("quantity")
|
||||
val quantity: Int,
|
||||
|
@ -11,81 +11,119 @@ data class OrderListResponse(
|
||||
val message: String
|
||||
)
|
||||
|
||||
data class OrdersItem(
|
||||
data class OrderItemsItem(
|
||||
|
||||
@field:SerializedName("receipt_num")
|
||||
val receiptNum: String,
|
||||
@field:SerializedName("review_id")
|
||||
val reviewId: Int? = null,
|
||||
|
||||
@field:SerializedName("latitude")
|
||||
val latitude: String,
|
||||
@field:SerializedName("quantity")
|
||||
val quantity: Int,
|
||||
|
||||
@field:SerializedName("created_at")
|
||||
val createdAt: String,
|
||||
@field:SerializedName("price")
|
||||
val price: Int,
|
||||
|
||||
@field:SerializedName("voucher_code")
|
||||
val voucherCode: String? = null,
|
||||
@field:SerializedName("subtotal")
|
||||
val subtotal: Int,
|
||||
|
||||
@field:SerializedName("updated_at")
|
||||
val updatedAt: String,
|
||||
@field:SerializedName("product_image")
|
||||
val productImage: String,
|
||||
|
||||
@field:SerializedName("street")
|
||||
val street: String,
|
||||
@field:SerializedName("store_name")
|
||||
val storeName: String,
|
||||
|
||||
@field:SerializedName("longitude")
|
||||
val longitude: String,
|
||||
@field:SerializedName("product_price")
|
||||
val productPrice: Int,
|
||||
|
||||
@field:SerializedName("shipment_status")
|
||||
val shipmentStatus: String,
|
||||
|
||||
@field:SerializedName("order_items")
|
||||
val orderItems: List<OrderItemsItem>,
|
||||
|
||||
@field:SerializedName("is_store_location")
|
||||
val isStoreLocation: Boolean,
|
||||
|
||||
@field:SerializedName("voucher_name")
|
||||
val voucherName: String? = null,
|
||||
|
||||
@field:SerializedName("address_id")
|
||||
val addressId: Int,
|
||||
|
||||
@field:SerializedName("payment_method_id")
|
||||
val paymentMethodId: Int,
|
||||
|
||||
@field:SerializedName("total_amount")
|
||||
val totalAmount: String,
|
||||
|
||||
@field:SerializedName("user_id")
|
||||
val userId: Int,
|
||||
|
||||
@field:SerializedName("province_id")
|
||||
val provinceId: Int,
|
||||
|
||||
@field:SerializedName("courier")
|
||||
val courier: String,
|
||||
|
||||
@field:SerializedName("subdistrict")
|
||||
val subdistrict: String,
|
||||
|
||||
@field:SerializedName("service")
|
||||
val service: String,
|
||||
|
||||
@field:SerializedName("shipment_price")
|
||||
val shipmentPrice: String,
|
||||
|
||||
@field:SerializedName("voucher_id")
|
||||
val voucherId: Int? = null,
|
||||
|
||||
@field:SerializedName("detail")
|
||||
val detail: String,
|
||||
|
||||
@field:SerializedName("postal_code")
|
||||
val postalCode: String,
|
||||
|
||||
@field:SerializedName("order_id")
|
||||
val orderId: Int,
|
||||
|
||||
@field:SerializedName("city_id")
|
||||
val cityId: Int
|
||||
@field:SerializedName("product_name")
|
||||
val productName: String
|
||||
)
|
||||
|
||||
data class OrdersItem(
|
||||
|
||||
@field:SerializedName("receipt_num")
|
||||
val receiptNum: Int? = null,
|
||||
|
||||
@field:SerializedName("latitude")
|
||||
val latitude: String,
|
||||
|
||||
@field:SerializedName("created_at")
|
||||
val createdAt: String,
|
||||
|
||||
@field:SerializedName("voucher_code")
|
||||
val voucherCode: String? = null,
|
||||
|
||||
@field:SerializedName("updated_at")
|
||||
val updatedAt: String,
|
||||
|
||||
@field:SerializedName("etd")
|
||||
val etd: String,
|
||||
|
||||
@field:SerializedName("street")
|
||||
val street: String,
|
||||
|
||||
@field:SerializedName("cancel_date")
|
||||
val cancelDate: String? = null,
|
||||
|
||||
@field:SerializedName("longitude")
|
||||
val longitude: String,
|
||||
|
||||
@field:SerializedName("shipment_status")
|
||||
val shipmentStatus: String,
|
||||
|
||||
@field:SerializedName("order_items")
|
||||
val orderItems: List<OrderItemsItem>,
|
||||
|
||||
@field:SerializedName("auto_completed_at")
|
||||
val autoCompletedAt: String? = null,
|
||||
|
||||
@field:SerializedName("is_store_location")
|
||||
val isStoreLocation: Boolean? = null,
|
||||
|
||||
@field:SerializedName("voucher_name")
|
||||
val voucherName: String? = null,
|
||||
|
||||
@field:SerializedName("address_id")
|
||||
val addressId: Int,
|
||||
|
||||
@field:SerializedName("cancel_reason")
|
||||
val cancelReason: String? = null,
|
||||
|
||||
@field:SerializedName("total_amount")
|
||||
val totalAmount: String,
|
||||
|
||||
@field:SerializedName("user_id")
|
||||
val userId: Int,
|
||||
|
||||
@field:SerializedName("province_id")
|
||||
val provinceId: Int,
|
||||
|
||||
@field:SerializedName("courier")
|
||||
val courier: String,
|
||||
|
||||
@field:SerializedName("subdistrict")
|
||||
val subdistrict: String,
|
||||
|
||||
@field:SerializedName("service")
|
||||
val service: String,
|
||||
|
||||
@field:SerializedName("shipment_price")
|
||||
val shipmentPrice: String,
|
||||
|
||||
@field:SerializedName("voucher_id")
|
||||
val voucherId: Int? = null,
|
||||
|
||||
@field:SerializedName("payment_info_id")
|
||||
val paymentInfoId: Int? = null,
|
||||
|
||||
@field:SerializedName("detail")
|
||||
val detail: String,
|
||||
|
||||
@field:SerializedName("postal_code")
|
||||
val postalCode: String,
|
||||
|
||||
@field:SerializedName("order_id")
|
||||
val orderId: Int,
|
||||
|
||||
@field:SerializedName("city_id")
|
||||
val cityId: Int
|
||||
)
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.alya.ecommerce_serang.data.api.retrofit
|
||||
|
||||
import com.alya.ecommerce_serang.data.api.dto.AddEvidenceRequest
|
||||
import com.alya.ecommerce_serang.data.api.dto.CartItem
|
||||
import com.alya.ecommerce_serang.data.api.dto.CourierCostRequest
|
||||
import com.alya.ecommerce_serang.data.api.dto.CreateAddressRequest
|
||||
@ -16,10 +17,13 @@ import com.alya.ecommerce_serang.data.api.response.auth.RegisterResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.cart.AddCartResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.cart.ListCartResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.cart.UpdateCartResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.order.AddEvidenceResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.order.CourierCostResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.order.CreateOrderResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.order.ListCityResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.order.ListProvinceResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.order.OrderDetailResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.order.OrderListResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.product.AllProductResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.product.CategoryResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.product.DetailStoreProductResponse
|
||||
@ -85,6 +89,21 @@ interface ApiService {
|
||||
@Body request: OrderRequest
|
||||
): Response<CreateOrderResponse>
|
||||
|
||||
@GET("order/detail/{id}")
|
||||
suspend fun getDetailOrder(
|
||||
@Path("id") orderId: Int
|
||||
): Response<OrderDetailResponse>
|
||||
|
||||
@POST("order/addevidence")
|
||||
suspend fun addEvidence(
|
||||
@Body request : AddEvidenceRequest,
|
||||
): Response<AddEvidenceResponse>
|
||||
|
||||
@GET("order/{status}")
|
||||
suspend fun getOrderList(
|
||||
@Path("status") status: String
|
||||
):Response<OrderListResponse>
|
||||
|
||||
@POST("order")
|
||||
suspend fun postOrderBuyNow(
|
||||
@Body request: OrderRequestBuy
|
||||
|
@ -1,16 +1,20 @@
|
||||
package com.alya.ecommerce_serang.data.repository
|
||||
|
||||
import android.util.Log
|
||||
import com.alya.ecommerce_serang.data.api.dto.AddEvidenceRequest
|
||||
import com.alya.ecommerce_serang.data.api.dto.CourierCostRequest
|
||||
import com.alya.ecommerce_serang.data.api.dto.CreateAddressRequest
|
||||
import com.alya.ecommerce_serang.data.api.dto.OrderRequest
|
||||
import com.alya.ecommerce_serang.data.api.dto.OrderRequestBuy
|
||||
import com.alya.ecommerce_serang.data.api.dto.UserProfile
|
||||
import com.alya.ecommerce_serang.data.api.response.cart.DataItem
|
||||
import com.alya.ecommerce_serang.data.api.response.order.AddEvidenceResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.order.CourierCostResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.order.CreateOrderResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.order.ListCityResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.order.ListProvinceResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.order.OrderDetailResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.order.OrderListResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.product.ProductResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.product.StoreProduct
|
||||
import com.alya.ecommerce_serang.data.api.response.product.StoreResponse
|
||||
@ -232,4 +236,59 @@ class OrderRepository(private val apiService: ApiService) {
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getOrderDetails(orderId: Int): OrderDetailResponse? {
|
||||
val response = apiService.getDetailOrder(orderId)
|
||||
return if (response.isSuccessful) response.body() else null
|
||||
}
|
||||
|
||||
suspend fun uploadPaymentProof(request : AddEvidenceRequest): Result<AddEvidenceResponse> {
|
||||
return try {
|
||||
Log.d("OrderRepository", "Add Evidence : $request")
|
||||
val response = apiService.addEvidence(request)
|
||||
|
||||
if (response.isSuccessful) {
|
||||
val addEvidenceResponse = response.body()
|
||||
if (addEvidenceResponse != null) {
|
||||
Log.d("OrderRepository", "Add Evidence successfully: ${addEvidenceResponse.message}")
|
||||
Result.Success(addEvidenceResponse)
|
||||
} else {
|
||||
Log.e("OrderRepository", "Response body was null")
|
||||
Result.Error(Exception("Empty response from server"))
|
||||
}
|
||||
} else {
|
||||
val errorBody = response.errorBody()?.string() ?: "Unknown error"
|
||||
Log.e("OrderRepository", "Error Add Evidence : $errorBody")
|
||||
Result.Error(Exception(errorBody))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("OrderRepository", "Exception Add Evidence ", e)
|
||||
Result.Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getOrderList(status: String): Result<OrderListResponse> {
|
||||
return try {
|
||||
Log.d("OrderRepository", "Add Evidence : $status")
|
||||
val response = apiService.getOrderList(status)
|
||||
|
||||
if (response.isSuccessful) {
|
||||
val allListOrder = response.body()
|
||||
if (allListOrder != null) {
|
||||
Log.d("OrderRepository", "Add Evidence successfully: ${allListOrder.message}")
|
||||
Result.Success(allListOrder)
|
||||
} else {
|
||||
Log.e("OrderRepository", "Response body was null")
|
||||
Result.Error(Exception("Empty response from server"))
|
||||
}
|
||||
} else {
|
||||
val errorBody = response.errorBody()?.string() ?: "Unknown error"
|
||||
Log.e("OrderRepository", "Error Add Evidence : $errorBody")
|
||||
Result.Error(Exception(errorBody))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("OrderRepository", "Exception Add Evidence ", e)
|
||||
Result.Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package com.alya.ecommerce_serang.ui.order.detail
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import com.alya.ecommerce_serang.R
|
||||
|
||||
class PaymentActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
setContentView(R.layout.activity_payment)
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
|
||||
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
|
||||
insets
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package com.alya.ecommerce_serang.ui.order.history
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.commit
|
||||
import com.alya.ecommerce_serang.R
|
||||
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
|
||||
import com.alya.ecommerce_serang.data.repository.OrderRepository
|
||||
import com.alya.ecommerce_serang.databinding.ActivityHistoryBinding
|
||||
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
||||
import com.alya.ecommerce_serang.utils.SessionManager
|
||||
|
||||
class HistoryActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivityHistoryBinding
|
||||
private lateinit var sessionManager: SessionManager
|
||||
|
||||
private val viewModel: HistoryViewModel by viewModels {
|
||||
BaseViewModelFactory {
|
||||
val apiService = ApiConfig.getApiService(sessionManager)
|
||||
val orderRepository = OrderRepository(apiService)
|
||||
HistoryViewModel(orderRepository)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityHistoryBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
sessionManager = SessionManager(this)
|
||||
|
||||
setupToolbar()
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
showOrderFragment()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupToolbar() {
|
||||
setSupportActionBar(binding.toolbar)
|
||||
supportActionBar?.setDisplayShowTitleEnabled(false)
|
||||
|
||||
binding.btnBack.setOnClickListener {
|
||||
onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun showOrderFragment() {
|
||||
supportFragmentManager.commit {
|
||||
replace(R.id.fragment_container_history, OrderHistoryFragment())
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package com.alya.ecommerce_serang.ui.order.history
|
||||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.alya.ecommerce_serang.data.api.response.order.OrdersItem
|
||||
import com.alya.ecommerce_serang.data.repository.OrderRepository
|
||||
import com.alya.ecommerce_serang.data.repository.Result
|
||||
import com.alya.ecommerce_serang.ui.order.address.ViewState
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class HistoryViewModel(private val repository: OrderRepository) : ViewModel() {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "HistoryViewModel"
|
||||
}
|
||||
|
||||
private val _orders = MutableLiveData<ViewState<List<OrdersItem>>>()
|
||||
val orders: LiveData<ViewState<List<OrdersItem>>> = _orders
|
||||
|
||||
fun getOrderList(status: String) {
|
||||
_orders.value = ViewState.Loading
|
||||
viewModelScope.launch {
|
||||
_orders.value = ViewState.Loading
|
||||
|
||||
try {
|
||||
when (val result = repository.getOrderList(status)) {
|
||||
is Result.Success -> {
|
||||
_orders.value = ViewState.Success(result.data.orders)
|
||||
Log.d("HistoryViewModel", "Orders loaded successfully: ${result.data.orders.size} items")
|
||||
}
|
||||
is Result.Error -> {
|
||||
_orders.value = ViewState.Error(result.exception.message ?: "Unknown error occurred")
|
||||
Log.e("HistoryViewModel", "Error loading orders", result.exception)
|
||||
}
|
||||
is Result.Loading -> {
|
||||
null
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
_orders.value = ViewState.Error("An unexpected error occurred: ${e.message}")
|
||||
Log.e("HistoryViewModel", "Exception in getOrderList", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
package com.alya.ecommerce_serang.ui.order.history
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.alya.ecommerce_serang.R
|
||||
import com.alya.ecommerce_serang.data.api.response.order.OrdersItem
|
||||
|
||||
class OrderHistoryAdapter(
|
||||
private val onOrderClickListener: (OrdersItem) -> Unit
|
||||
) : RecyclerView.Adapter<OrderHistoryAdapter.OrderViewHolder>() {
|
||||
|
||||
private val orders = mutableListOf<OrdersItem>()
|
||||
|
||||
fun submitList(newOrders: List<OrdersItem>) {
|
||||
orders.clear()
|
||||
orders.addAll(newOrders)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OrderViewHolder {
|
||||
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_order_history, parent, false)
|
||||
return OrderViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: OrderViewHolder, position: Int) {
|
||||
holder.bind(orders[position])
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = orders.size
|
||||
|
||||
inner class OrderViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
private val tvStoreName: TextView = itemView.findViewById(R.id.tvStoreName)
|
||||
private val tvOrderStatus: TextView = itemView.findViewById(R.id.tvOrderStatus)
|
||||
private val rvOrderItems: RecyclerView = itemView.findViewById(R.id.rvOrderItems)
|
||||
private val tvShowMore: TextView = itemView.findViewById(R.id.tvShowMore)
|
||||
private val tvTotalAmount: TextView = itemView.findViewById(R.id.tvTotalAmount)
|
||||
private val tvItemCountLabel: TextView = itemView.findViewById(R.id.tv_count_total_item)
|
||||
private val tvDeadlineDate: TextView = itemView.findViewById(R.id.tvDeadlineDate)
|
||||
|
||||
fun bind(order: OrdersItem) {
|
||||
// Get store name from the first order item
|
||||
val storeName = if (order.orderItems.isNotEmpty()) order.orderItems[0].storeName else ""
|
||||
tvStoreName.text = storeName
|
||||
|
||||
// Set order status based on shipment status
|
||||
tvOrderStatus.text = getStatusLabel(order.shipmentStatus)
|
||||
|
||||
// Set total amount
|
||||
tvTotalAmount.text = order.totalAmount
|
||||
|
||||
// Set item count
|
||||
val itemCount = order.orderItems.size
|
||||
tvItemCountLabel.text = itemView.context.getString(R.string.item_count_prod, itemCount)
|
||||
|
||||
// Set deadline date
|
||||
tvDeadlineDate.text = formatDate(order.createdAt) // This would need a proper date formatting function
|
||||
|
||||
// Set up the order items RecyclerView
|
||||
val productAdapter = OrderProductAdapter()
|
||||
rvOrderItems.apply {
|
||||
layoutManager = LinearLayoutManager(itemView.context)
|
||||
adapter = productAdapter
|
||||
}
|
||||
|
||||
// Display only the first product and show "View more" for the rest
|
||||
if (order.orderItems.isNotEmpty()) {
|
||||
productAdapter.submitList(order.orderItems.take(1))
|
||||
|
||||
// Show or hide the "View more" text based on number of items
|
||||
if (order.orderItems.size > 1) {
|
||||
val itemString = order.orderItems.size - 1
|
||||
tvShowMore.visibility = View.VISIBLE
|
||||
tvShowMore.text = itemView.context.getString(R.string.show_more_product, itemString)
|
||||
} else {
|
||||
tvShowMore.visibility = View.GONE
|
||||
}
|
||||
} else {
|
||||
tvShowMore.visibility = View.GONE
|
||||
}
|
||||
|
||||
// Set click listener for the entire order item
|
||||
itemView.setOnClickListener {
|
||||
onOrderClickListener(order)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getStatusLabel(status: String): String {
|
||||
return when (status.toLowerCase()) {
|
||||
"pending" -> itemView.context.getString(R.string.pending_orders)
|
||||
"unpaid" -> itemView.context.getString(R.string.unpaid_orders)
|
||||
"processed" -> itemView.context.getString(R.string.processed_orders)
|
||||
"paid" -> itemView.context.getString(R.string.paid_orders)
|
||||
"shipped" -> itemView.context.getString(R.string.shipped_orders)
|
||||
"delivered" -> itemView.context.getString(R.string.delivered_orders)
|
||||
"completed" -> itemView.context.getString(R.string.completed_orders)
|
||||
"canceled" -> itemView.context.getString(R.string.canceled_orders)
|
||||
else -> status
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatDate(dateString: String): String {
|
||||
// In a real app, you would parse the date string and format it
|
||||
// For this example, just return the string as is
|
||||
return dateString
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package com.alya.ecommerce_serang.ui.order.history
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.alya.ecommerce_serang.R
|
||||
import com.alya.ecommerce_serang.databinding.FragmentOrderHistoryBinding
|
||||
import com.alya.ecommerce_serang.utils.SessionManager
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
|
||||
class OrderHistoryFragment : Fragment() {
|
||||
|
||||
private var _binding: FragmentOrderHistoryBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private lateinit var sessionManager: SessionManager
|
||||
|
||||
|
||||
private lateinit var viewPagerAdapter: OrderViewPagerAdapter
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentOrderHistoryBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
sessionManager = SessionManager(requireContext())
|
||||
|
||||
setupViewPager()
|
||||
}
|
||||
|
||||
private fun setupViewPager() {
|
||||
// Initialize the ViewPager adapter
|
||||
viewPagerAdapter = OrderViewPagerAdapter(requireActivity())
|
||||
binding.viewPager.adapter = viewPagerAdapter
|
||||
|
||||
// Connect TabLayout with ViewPager2
|
||||
TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
|
||||
tab.text = when (position) {
|
||||
0 -> getString(R.string.all_orders)
|
||||
1 -> getString(R.string.pending_orders)
|
||||
2 -> getString(R.string.unpaid_orders)
|
||||
3 -> getString(R.string.processed_orders)
|
||||
4 -> getString(R.string.paid_orders)
|
||||
5 -> getString(R.string.shipped_orders)
|
||||
6 -> getString(R.string.delivered_orders)
|
||||
7 -> getString(R.string.completed_orders)
|
||||
8 -> getString(R.string.canceled_orders)
|
||||
else -> "Tab $position"
|
||||
}
|
||||
}.attach()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
package com.alya.ecommerce_serang.ui.order.history
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.alya.ecommerce_serang.data.api.response.order.OrdersItem
|
||||
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
|
||||
import com.alya.ecommerce_serang.data.repository.OrderRepository
|
||||
import com.alya.ecommerce_serang.databinding.FragmentOrderListBinding
|
||||
import com.alya.ecommerce_serang.ui.order.address.ViewState
|
||||
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
||||
import com.alya.ecommerce_serang.utils.SessionManager
|
||||
|
||||
class OrderListFragment : Fragment() {
|
||||
|
||||
private var _binding: FragmentOrderListBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private lateinit var sessionManager: SessionManager
|
||||
|
||||
|
||||
private val viewModel: HistoryViewModel by viewModels {
|
||||
BaseViewModelFactory {
|
||||
val apiService = ApiConfig.getApiService(sessionManager)
|
||||
val orderRepository = OrderRepository(apiService)
|
||||
HistoryViewModel(orderRepository)
|
||||
}
|
||||
}
|
||||
private lateinit var orderAdapter: OrderHistoryAdapter
|
||||
|
||||
private var status: String = "all"
|
||||
|
||||
companion object {
|
||||
private const val ARG_STATUS = "status"
|
||||
|
||||
fun newInstance(status: String): OrderListFragment {
|
||||
return OrderListFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putString(ARG_STATUS, status)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
sessionManager = SessionManager(requireContext())
|
||||
arguments?.let {
|
||||
status = it.getString(ARG_STATUS) ?: "all"
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentOrderListBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setupRecyclerView()
|
||||
observeOrderList()
|
||||
loadOrders()
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
orderAdapter = OrderHistoryAdapter { order ->
|
||||
// Handle order click
|
||||
navigateToOrderDetail(order)
|
||||
}
|
||||
|
||||
binding.rvOrders.apply {
|
||||
layoutManager = LinearLayoutManager(requireContext())
|
||||
adapter = orderAdapter
|
||||
}
|
||||
}
|
||||
|
||||
private fun observeOrderList() {
|
||||
viewModel.orders.observe(viewLifecycleOwner) { result ->
|
||||
when (result) {
|
||||
is ViewState.Success -> {
|
||||
binding.progressBar.visibility = View.GONE
|
||||
|
||||
if (result.data.isNullOrEmpty()) {
|
||||
binding.tvEmptyState.visibility = View.VISIBLE
|
||||
binding.rvOrders.visibility = View.GONE
|
||||
} else {
|
||||
binding.tvEmptyState.visibility = View.GONE
|
||||
binding.rvOrders.visibility = View.VISIBLE
|
||||
orderAdapter.submitList(result.data)
|
||||
}
|
||||
}
|
||||
is ViewState.Error -> {
|
||||
binding.progressBar.visibility = View.GONE
|
||||
binding.tvEmptyState.visibility = View.VISIBLE
|
||||
Toast.makeText(requireContext(), result.message, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
is ViewState.Loading -> {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadOrders() {
|
||||
viewModel.getOrderList(status)
|
||||
}
|
||||
|
||||
private fun navigateToOrderDetail(order: OrdersItem) {
|
||||
// In a real app, you would navigate to order detail screen
|
||||
// For example: findNavController().navigate(OrderListFragmentDirections.actionToOrderDetail(order.orderId))
|
||||
Toast.makeText(requireContext(), "Order ID: ${order.orderId}", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package com.alya.ecommerce_serang.ui.order.history
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.alya.ecommerce_serang.R
|
||||
import com.alya.ecommerce_serang.data.api.response.order.OrderItemsItem
|
||||
import com.bumptech.glide.Glide
|
||||
|
||||
class OrderProductAdapter : RecyclerView.Adapter<OrderProductAdapter.ProductViewHolder>() {
|
||||
|
||||
private val products = mutableListOf<OrderItemsItem>()
|
||||
|
||||
fun submitList(newProducts: List<OrderItemsItem>) {
|
||||
products.clear()
|
||||
products.addAll(newProducts)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductViewHolder {
|
||||
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_order_product, parent, false)
|
||||
return ProductViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ProductViewHolder, position: Int) {
|
||||
holder.bind(products[position])
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = products.size
|
||||
|
||||
inner class ProductViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
private val ivProductImage: ImageView = itemView.findViewById(R.id.iv_product)
|
||||
private val tvProductName: TextView = itemView.findViewById(R.id.tv_product_name)
|
||||
private val tvQuantity: TextView = itemView.findViewById(R.id.tv_product_quantity)
|
||||
private val tvProductPrice: TextView = itemView.findViewById(R.id.tv_product_price)
|
||||
|
||||
fun bind(product: OrderItemsItem) {
|
||||
// Set product name
|
||||
tvProductName.text = product.productName
|
||||
|
||||
// Set quantity with suffix
|
||||
tvQuantity.text = "${product.quantity} buah"
|
||||
|
||||
// Set price with currency format
|
||||
tvProductPrice.text = formatCurrency(product.price)
|
||||
|
||||
// Load product image using Glide
|
||||
Glide.with(itemView.context)
|
||||
.load(product.productImage)
|
||||
.placeholder(R.drawable.placeholder_image)
|
||||
// .error(R.drawable.error_image)
|
||||
.into(ivProductImage)
|
||||
}
|
||||
|
||||
private fun formatCurrency(amount: Int): String {
|
||||
// In a real app, you would use NumberFormat for proper currency formatting
|
||||
// For simplicity, just return a basic formatted string
|
||||
return "Rp${amount}"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.alya.ecommerce_serang.ui.order.history
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
|
||||
class OrderViewPagerAdapter(
|
||||
fragmentActivity: FragmentActivity
|
||||
) : FragmentStateAdapter(fragmentActivity) {
|
||||
|
||||
// Define all possible order statuses
|
||||
private val orderStatuses = listOf(
|
||||
"all", // All orders
|
||||
"pending", // Menunggu Tagihan
|
||||
"unpaid", // Belum Dibayar
|
||||
"processed", // Diproses
|
||||
"paid", // Dibayar
|
||||
"shipped", // Dikirim
|
||||
"delivered", // Diterima
|
||||
"completed", // Selesai
|
||||
"canceled" // Dibatalkan
|
||||
)
|
||||
|
||||
override fun getItemCount(): Int = orderStatuses.size
|
||||
|
||||
override fun createFragment(position: Int): Fragment {
|
||||
// Create a new instance of OrderListFragment with the appropriate status
|
||||
return OrderListFragment.newInstance(orderStatuses[position])
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ import com.alya.ecommerce_serang.data.api.dto.UserProfile
|
||||
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
|
||||
import com.alya.ecommerce_serang.data.repository.UserRepository
|
||||
import com.alya.ecommerce_serang.databinding.FragmentProfileBinding
|
||||
import com.alya.ecommerce_serang.ui.order.history.HistoryActivity
|
||||
import com.alya.ecommerce_serang.ui.profile.mystore.MyStoreActivity
|
||||
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
||||
import com.alya.ecommerce_serang.utils.SessionManager
|
||||
@ -63,6 +64,16 @@ class ProfileFragment : Fragment() {
|
||||
val intentDetail = Intent(requireContext(), DetailProfileActivity::class.java)
|
||||
startActivity(intentDetail)
|
||||
}
|
||||
|
||||
binding.tvLihatRiwayat.setOnClickListener{
|
||||
val intent = Intent(requireContext(), HistoryActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
binding.cardPesanan.setOnClickListener{
|
||||
val intent = Intent(requireContext(), HistoryActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
private fun observeUserProfile() {
|
||||
|
6
app/src/main/res/drawable/bg_button_filled.xml
Normal file
6
app/src/main/res/drawable/bg_button_filled.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/blue_500" />
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
9
app/src/main/res/drawable/bg_button_outline.xml
Normal file
9
app/src/main/res/drawable/bg_button_outline.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@android:color/white" />
|
||||
<corners android:radius="8dp" />
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="@color/white" />
|
||||
</shape>
|
58
app/src/main/res/layout/activity_history.xml
Normal file
58
app/src/main/res/layout/activity_history.xml
Normal file
@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ui.order.history.HistoryActivity">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/white"
|
||||
android:elevation="4dp"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnBack"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="Kembali"
|
||||
android:src="@drawable/ic_back_24"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:text="Riwayat Pesanan"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/btnBack"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/fragment_container_history"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/toolbar" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
262
app/src/main/res/layout/activity_payment.xml
Normal file
262
app/src/main/res/layout/activity_payment.xml
Normal file
@ -0,0 +1,262 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ui.order.detail.PaymentActivity">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="@android:color/white"
|
||||
app:navigationIcon="@drawable/ic_arrow_back">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Pembayaran"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/buttonLayout"
|
||||
app:layout_constraintTop_toBottomOf="@id/appBarLayout">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Total Bayar"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTotalAmount"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:text="Rp75.000"
|
||||
android:textColor="@color/blue_500"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="#E0E0E0" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="Bayar Dalam"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvRemainingTime"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="end"
|
||||
android:text="23 jam 15 menit"
|
||||
android:textColor="@color/blue_500"
|
||||
android:textSize="16sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvDueDate"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:text="Jatuh tempo 15 Nov 2024"
|
||||
android:textColor="#808080"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="2dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivBankLogo"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:src="@drawable/outline_store_24" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Nomor Rekening:"
|
||||
android:textColor="#808080"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvAccountNumber"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="01233435436363757537856"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvBankName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Bank BCA"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="#E0E0E0" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutMBankingInstructions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Petunjuk Transfer mBanking"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/ic_arrow_right" />
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="#E0E0E0" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutATMInstructions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Petunjuk Transfer ATM"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/ic_arrow_right" />
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="#E0E0E0" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="Detail Pesanan"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvOrderItems"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:itemCount="2"
|
||||
tools:listitem="@layout/item_order_product" />
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/buttonLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnNegotiatePrice"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="@drawable/bg_button_outline"
|
||||
android:text="Negosiasi Harga"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="@color/blue_500" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnUploadPaymentProof"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_button_filled"
|
||||
android:text="Kirim Bukti Bayar"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="@android:color/white" />
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
26
app/src/main/res/layout/fragment_order_history.xml
Normal file
26
app/src/main/res/layout/fragment_order_history.xml
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tabLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/white"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:tabGravity="fill"
|
||||
app:tabIndicatorColor="@color/blue_200"
|
||||
app:tabMode="scrollable"
|
||||
app:tabSelectedTextColor="@color/blue_200"
|
||||
app:tabTextColor="@android:color/darker_gray" />
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/viewPager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tabLayout" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
40
app/src/main/res/layout/fragment_order_list.xml
Normal file
40
app/src/main/res/layout/fragment_order_list.xml
Normal file
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#F5F5F5">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvOrders"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:padding="8dp"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:listitem="@layout/item_order_history" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvEmptyState"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/no_available_orders"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
157
app/src/main/res/layout/item_order_history.xml
Normal file
157
app/src/main/res/layout/item_order_history.xml
Normal file
@ -0,0 +1,157 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="2dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvStoreName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="SnackEnak" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvOrderStatus"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/blue_500"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Menunggu Tagihan" />
|
||||
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="#E0E0E0"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvStoreName" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvOrderItems"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
app:layout_constraintTop_toBottomOf="@+id/divider"
|
||||
tools:itemCount="1"
|
||||
tools:listitem="@layout/item_order_product" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvShowMore"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="center_vertical"
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/rvOrderItems"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
tools:text="@string/show_more_product" />
|
||||
|
||||
<View
|
||||
android:id="@+id/divider2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="#E0E0E0"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvShowMore" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_count_total_item"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/item_count_prod"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="@font/dmsans_bold"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/divider2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTotalLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/total_order"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="@font/dmsans_bold"
|
||||
app:layout_constraintEnd_toStartOf="@+id/tvTotalAmount"
|
||||
app:layout_constraintTop_toBottomOf="@+id/divider2"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTotalAmount"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="@font/dmsans_semibold"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/divider2"
|
||||
tools:text="Rp500.000" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvDeadlineLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/batas_tagihan"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tv_count_total_item" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvDeadlineDate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintStart_toEndOf="@+id/tvDeadlineLabel"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tv_count_total_item"
|
||||
tools:text="28 Oktober 2024" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_left"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_button_outline"
|
||||
android:backgroundTint="@color/white"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvDeadlineDate"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:layout_marginTop="8dp"/>
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_right"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_button_filled"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:text="Kirim Bukti Bayar"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvDeadlineDate"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginTop="8dp"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.cardview.widget.CardView>
|
57
app/src/main/res/layout/item_order_history_prod.xml
Normal file
57
app/src/main/res/layout/item_order_history_prod.xml
Normal file
@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivProductImage"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:background="#F0F0F0"
|
||||
android:scaleType="centerCrop"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@tools:sample/avatars" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvProductName"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintEnd_toStartOf="@+id/tvProductPrice"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivProductImage"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Jaket Pink Fuschia" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvQuantity"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivProductImage"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tvProductName"
|
||||
tools:text="2 buah" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvProductPrice"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Rp150.000" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
75
app/src/main/res/layout/item_order_payment.xml
Normal file
75
app/src/main/res/layout/item_order_payment.xml
Normal file
@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="2dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="12dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivProductImage"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
android:scaleType="centerCrop"
|
||||
tools:src="@drawable/placeholder_image" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvStoreName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#808080"
|
||||
android:textSize="14sp"
|
||||
tools:text="Store Name" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvProductName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="16sp"
|
||||
tools:text="Product Name with potentially long description that might get truncated" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvProductPrice"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textColor="@color/blue_500"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
tools:text="Rp50.000" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvQuantity"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#808080"
|
||||
android:textSize="14sp"
|
||||
tools:text="x2" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
@ -61,4 +61,21 @@
|
||||
<string name="add_to_cart">Keranjang</string>
|
||||
<string name="beli_sekarang">Beli Sekarang</string>
|
||||
<string name="hello_blank_fragment">Hello blank fragment</string>
|
||||
<string name="batas_tagihan">Batas Tagihan :</string>
|
||||
<string name="total_order">Total: </string>
|
||||
<string name="dl_date_wait">23:59 15 April 2025</string>
|
||||
<string name="no_available_orders">Tidak ada order</string>
|
||||
<string name="item_count_prod">%d produk</string>
|
||||
<string name="show_more_product">%d produk lainnya</string>
|
||||
<!-- status order-->
|
||||
<string name="all_orders">Semua Pesanan </string>
|
||||
<string name="pending_orders">Menunggu Tagihan</string>
|
||||
<string name="unpaid_orders">Konfrimasi Bayar</string>
|
||||
<string name="processed_orders">Diproses</string>
|
||||
<string name="paid_orders">Sudah Dibayar</string>
|
||||
<string name="delivered_orders">Pesanan Sampai</string>
|
||||
<string name="completed_orders">Selesai</string>
|
||||
<string name="shipped_orders">Dikirim</string>
|
||||
<string name="canceled_orders">Dibatalkan</string>
|
||||
|
||||
</resources>
|
Reference in New Issue
Block a user