diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c1cfce9..e47879a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -19,6 +19,12 @@
android:theme="@style/Theme.Ecommerce_serang"
android:usesCleartextTraffic="true"
tools:targetApi="31">
+
+
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/AddEvidenceRequest.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/AddEvidenceRequest.kt
new file mode 100644
index 0000000..baee00c
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/AddEvidenceRequest.kt
@@ -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
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/order/AddEvidenceResponse.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/order/AddEvidenceResponse.kt
new file mode 100644
index 0000000..4fe220e
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/order/AddEvidenceResponse.kt
@@ -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
+)
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/order/OrderDetailResponse.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/order/OrderDetailResponse.kt
index 20b6432..2e75e98 100644
--- a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/order/OrderDetailResponse.kt
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/order/OrderDetailResponse.kt
@@ -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,
+ val orderItems: List,
@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,
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/order/OrderListResponse.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/order/OrderListResponse.kt
index a962817..069d97d 100644
--- a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/order/OrderListResponse.kt
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/order/OrderListResponse.kt
@@ -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,
-
- @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,
+
+ @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
+)
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/retrofit/ApiService.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/retrofit/ApiService.kt
index 2367f28..e916206 100644
--- a/app/src/main/java/com/alya/ecommerce_serang/data/api/retrofit/ApiService.kt
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/retrofit/ApiService.kt
@@ -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
+ @GET("order/detail/{id}")
+ suspend fun getDetailOrder(
+ @Path("id") orderId: Int
+ ): Response
+
+ @POST("order/addevidence")
+ suspend fun addEvidence(
+ @Body request : AddEvidenceRequest,
+ ): Response
+
+ @GET("order/{status}")
+ suspend fun getOrderList(
+ @Path("status") status: String
+ ):Response
+
@POST("order")
suspend fun postOrderBuyNow(
@Body request: OrderRequestBuy
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/repository/OrderRepository.kt b/app/src/main/java/com/alya/ecommerce_serang/data/repository/OrderRepository.kt
index b4bc29a..36942f1 100644
--- a/app/src/main/java/com/alya/ecommerce_serang/data/repository/OrderRepository.kt
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/repository/OrderRepository.kt
@@ -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 {
+ 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 {
+ 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)
+ }
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/detail/PaymentActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/detail/PaymentActivity.kt
new file mode 100644
index 0000000..1ba879a
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/detail/PaymentActivity.kt
@@ -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
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/HistoryActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/HistoryActivity.kt
new file mode 100644
index 0000000..fdc7f1d
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/HistoryActivity.kt
@@ -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())
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/HistoryViewModel.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/HistoryViewModel.kt
new file mode 100644
index 0000000..7f65ae1
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/HistoryViewModel.kt
@@ -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>>()
+ val orders: LiveData>> = _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)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryAdapter.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryAdapter.kt
new file mode 100644
index 0000000..b1b13f4
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryAdapter.kt
@@ -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() {
+
+ private val orders = mutableListOf()
+
+ fun submitList(newOrders: List) {
+ 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
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryFragment.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryFragment.kt
new file mode 100644
index 0000000..b7d0f6e
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderHistoryFragment.kt
@@ -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
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderListFragment.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderListFragment.kt
new file mode 100644
index 0000000..6686484
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderListFragment.kt
@@ -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
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderProductAdapter.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderProductAdapter.kt
new file mode 100644
index 0000000..2cfcb16
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderProductAdapter.kt
@@ -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() {
+
+ private val products = mutableListOf()
+
+ fun submitList(newProducts: List) {
+ 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}"
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderViewPageAdapter.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderViewPageAdapter.kt
new file mode 100644
index 0000000..a759240
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/ui/order/history/OrderViewPageAdapter.kt
@@ -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])
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/ProfileFragment.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/ProfileFragment.kt
index 1465f3f..b527fd9 100644
--- a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/ProfileFragment.kt
+++ b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/ProfileFragment.kt
@@ -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() {
diff --git a/app/src/main/res/drawable/bg_button_filled.xml b/app/src/main/res/drawable/bg_button_filled.xml
new file mode 100644
index 0000000..967a6d9
--- /dev/null
+++ b/app/src/main/res/drawable/bg_button_filled.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_button_outline.xml b/app/src/main/res/drawable/bg_button_outline.xml
new file mode 100644
index 0000000..36bcbbf
--- /dev/null
+++ b/app/src/main/res/drawable/bg_button_outline.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_history.xml b/app/src/main/res/layout/activity_history.xml
new file mode 100644
index 0000000..bfa8178
--- /dev/null
+++ b/app/src/main/res/layout/activity_history.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_payment.xml b/app/src/main/res/layout/activity_payment.xml
new file mode 100644
index 0000000..731356b
--- /dev/null
+++ b/app/src/main/res/layout/activity_payment.xml
@@ -0,0 +1,262 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_order_history.xml b/app/src/main/res/layout/fragment_order_history.xml
new file mode 100644
index 0000000..e1221d7
--- /dev/null
+++ b/app/src/main/res/layout/fragment_order_history.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_order_list.xml b/app/src/main/res/layout/fragment_order_list.xml
new file mode 100644
index 0000000..2f45f6a
--- /dev/null
+++ b/app/src/main/res/layout/fragment_order_list.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_order_history.xml b/app/src/main/res/layout/item_order_history.xml
new file mode 100644
index 0000000..446897e
--- /dev/null
+++ b/app/src/main/res/layout/item_order_history.xml
@@ -0,0 +1,157 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_order_history_prod.xml b/app/src/main/res/layout/item_order_history_prod.xml
new file mode 100644
index 0000000..61b2966
--- /dev/null
+++ b/app/src/main/res/layout/item_order_history_prod.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_order_payment.xml b/app/src/main/res/layout/item_order_payment.xml
new file mode 100644
index 0000000..206f997
--- /dev/null
+++ b/app/src/main/res/layout/item_order_payment.xml
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 63f3852..898a920 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -61,4 +61,21 @@
Keranjang
Beli Sekarang
Hello blank fragment
+ Batas Tagihan :
+ Total:
+ 23:59 15 April 2025
+ Tidak ada order
+ %d produk
+ %d produk lainnya
+
+ Semua Pesanan
+ Menunggu Tagihan
+ Konfrimasi Bayar
+ Diproses
+ Sudah Dibayar
+ Pesanan Sampai
+ Selesai
+ Dikirim
+ Dibatalkan
+
\ No newline at end of file