update product

This commit is contained in:
Gracia
2025-04-19 20:49:38 +07:00
parent 3b0b2d602f
commit 181106eaf5
58 changed files with 731 additions and 221 deletions

View File

@ -22,7 +22,7 @@
android:usesCleartextTraffic="true" android:usesCleartextTraffic="true"
tools:targetApi="31"> tools:targetApi="31">
<activity <activity
android:name=".data.api.response.cart.CartActivity" android:name=".data.api.response.customer.cart.CartActivity"
android:exported="false" /> android:exported="false" />
<activity <activity
android:name=".ui.order.address.EditAddressActivity" android:name=".ui.order.address.EditAddressActivity"

View File

@ -1,6 +1,6 @@
package com.alya.ecommerce_serang.data.api.dto package com.alya.ecommerce_serang.data.api.dto
import com.alya.ecommerce_serang.data.api.response.cart.CartItemsItem import com.alya.ecommerce_serang.data.api.response.customer.cart.CartItemsItem
data class CheckoutData( data class CheckoutData(
val orderRequest: Any, // Can be OrderRequest or OrderRequestBuy val orderRequest: Any, // Can be OrderRequest or OrderRequestBuy

View File

@ -0,0 +1,15 @@
package com.alya.ecommerce_serang.data.api.dto
import com.google.gson.annotations.SerializedName
data class Preorder(
@field:SerializedName("duration")
val duration: Int? = null,
@field:SerializedName("product_id")
val productId: Int? = null,
@field:SerializedName("id")
val id: Int? = null
)

View File

@ -25,11 +25,14 @@ data class Product(
@field:SerializedName("is_pre_order") @field:SerializedName("is_pre_order")
val isPreOrder: Boolean? = null, val isPreOrder: Boolean? = null,
@field:SerializedName("condition")
val condition: String? = null,
@field:SerializedName("category_id") @field:SerializedName("category_id")
val categoryId: Int? = null, val categoryId: Int? = null,
@field:SerializedName("price") @field:SerializedName("price")
val price: Int? = null, val price: String? = null,
@field:SerializedName("name") @field:SerializedName("name")
val name: String? = null, val name: String? = null,

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.cart package com.alya.ecommerce_serang.data.api.response.customer.cart
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.cart package com.alya.ecommerce_serang.data.api.response.customer.cart
import android.os.Bundle import android.os.Bundle
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.cart package com.alya.ecommerce_serang.data.api.response.customer.cart
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.cart package com.alya.ecommerce_serang.data.api.response.customer.cart
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.order package com.alya.ecommerce_serang.data.api.response.customer.order
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.order package com.alya.ecommerce_serang.data.api.response.customer.order
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.order package com.alya.ecommerce_serang.data.api.response.customer.order
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.order package com.alya.ecommerce_serang.data.api.response.customer.order
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.order package com.alya.ecommerce_serang.data.api.response.customer.order
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.order package com.alya.ecommerce_serang.data.api.response.customer.order
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.product package com.alya.ecommerce_serang.data.api.response.customer.product
import com.alya.ecommerce_serang.data.api.dto.ProductsItem import com.alya.ecommerce_serang.data.api.dto.ProductsItem
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.product package com.alya.ecommerce_serang.data.api.response.customer.product
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.product package com.alya.ecommerce_serang.data.api.response.customer.product
import com.alya.ecommerce_serang.data.api.dto.CategoryItem import com.alya.ecommerce_serang.data.api.dto.CategoryItem
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.product package com.alya.ecommerce_serang.data.api.response.customer.product
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.product package com.alya.ecommerce_serang.data.api.response.customer.product
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.product package com.alya.ecommerce_serang.data.api.response.customer.product
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.product package com.alya.ecommerce_serang.data.api.response.customer.product
import com.alya.ecommerce_serang.data.api.dto.Store import com.alya.ecommerce_serang.data.api.dto.Store
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.profile package com.alya.ecommerce_serang.data.api.response.customer.profile
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.profile package com.alya.ecommerce_serang.data.api.response.customer.profile
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.profile package com.alya.ecommerce_serang.data.api.response.customer.profile
import com.alya.ecommerce_serang.data.api.dto.UserProfile import com.alya.ecommerce_serang.data.api.dto.UserProfile
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View File

@ -0,0 +1,9 @@
package com.alya.ecommerce_serang.data.api.response.store.orders
import com.google.gson.annotations.SerializedName
data class AddShippingReceiptResponse(
@field:SerializedName("message")
val message: String? = null
)

View File

@ -0,0 +1,48 @@
package com.alya.ecommerce_serang.data.api.response.store.orders
import com.google.gson.annotations.SerializedName
data class KonfirmasiTagihanResponse(
@field:SerializedName("message")
val message: String? = null,
@field:SerializedName("updatedOrder")
val updatedOrder: UpdatedOrder? = null,
@field:SerializedName("updatedItems")
val updatedItems: List<Any?>? = null
)
data class UpdatedOrder(
@field:SerializedName("payment_method_id")
val paymentMethodId: Int? = null,
@field:SerializedName("updated_at")
val updatedAt: String? = null,
@field:SerializedName("total_amount")
val totalAmount: String? = null,
@field:SerializedName("user_id")
val userId: Int? = null,
@field:SerializedName("address_id")
val addressId: Int? = null,
@field:SerializedName("is_negotiable")
val isNegotiable: Boolean? = null,
@field:SerializedName("created_at")
val createdAt: String? = null,
@field:SerializedName("voucher_id")
val voucherId: Any? = null,
@field:SerializedName("id")
val id: Int? = null,
@field:SerializedName("status")
val status: String? = null
)

View File

@ -0,0 +1,168 @@
package com.alya.ecommerce_serang.data.api.response.store.orders
import com.google.gson.annotations.SerializedName
data class OrderListResponse(
@field:SerializedName("orders")
val orders: List<OrdersItem?>? = null,
@field:SerializedName("message")
val message: String? = null
)
data class Voucher(
@field:SerializedName("name")
val name: Any? = null,
@field:SerializedName("voucher_id")
val voucherId: Any? = null,
@field:SerializedName("voucher_code")
val voucherCode: Any? = null
)
data class Shipment(
@field:SerializedName("receipt_num")
val receiptNum: Any? = null,
@field:SerializedName("courier")
val courier: Any? = null,
@field:SerializedName("price")
val price: Any? = null,
@field:SerializedName("service")
val service: Any? = null,
@field:SerializedName("shipment_id")
val shipmentId: Any? = null,
@field:SerializedName("status")
val status: Any? = null
)
data class OrderItemsItem(
@field:SerializedName("review_id")
val reviewId: Int? = null,
@field:SerializedName("quantity")
val quantity: Int? = null,
@field:SerializedName("price")
val price: Int? = null,
@field:SerializedName("subtotal")
val subtotal: Int? = null,
@field:SerializedName("product_image")
val productImage: String? = null,
@field:SerializedName("store_name")
val storeName: String? = null,
@field:SerializedName("product_price")
val productPrice: Int? = null,
@field:SerializedName("product_name")
val productName: String? = null
)
data class Address(
@field:SerializedName("is_store_location")
val isStoreLocation: Boolean? = null,
@field:SerializedName("province_id")
val provinceId: Int? = null,
@field:SerializedName("street")
val street: String? = null,
@field:SerializedName("subdistrict")
val subdistrict: String? = null,
@field:SerializedName("latitude")
val latitude: Any? = null,
@field:SerializedName("address_id")
val addressId: Int? = null,
@field:SerializedName("detail")
val detail: String? = null,
@field:SerializedName("postal_code")
val postalCode: String? = null,
@field:SerializedName("longitude")
val longitude: Any? = null,
@field:SerializedName("city_id")
val cityId: Int? = null
)
data class Payment(
@field:SerializedName("evidence")
val evidence: Any? = null,
@field:SerializedName("uploaded_at")
val uploadedAt: Any? = null,
@field:SerializedName("payment_id")
val paymentId: Any? = null
)
data class OrdersItem(
@field:SerializedName("address")
val address: Address? = null,
@field:SerializedName("shipment")
val shipment: Shipment? = null,
@field:SerializedName("voucher")
val voucher: Voucher? = null,
@field:SerializedName("address_id")
val addressId: Int? = null,
@field:SerializedName("is_negotiable")
val isNegotiable: Boolean? = null,
@field:SerializedName("created_at")
val createdAt: String? = null,
@field:SerializedName("payment_method_id")
val paymentMethodId: Int? = null,
@field:SerializedName("updated_at")
val updatedAt: String? = null,
@field:SerializedName("user_id")
val userId: Int? = null,
@field:SerializedName("total_amount")
val totalAmount: String? = null,
@field:SerializedName("voucher_id")
val voucherId: Any? = null,
@field:SerializedName("payment")
val payment: Payment? = null,
@field:SerializedName("order_id")
val orderId: Int? = null,
@field:SerializedName("username")
val username: String? = null,
@field:SerializedName("status")
val status: String? = null,
@field:SerializedName("order_items")
val orderItems: List<OrderItemsItem?>? = null
)

View File

@ -0,0 +1,9 @@
package com.alya.ecommerce_serang.data.api.response.store.orders
import com.google.gson.annotations.SerializedName
data class PaymentConfirmationResponse(
@field:SerializedName("message")
val message: String? = null
)

View File

@ -0,0 +1,75 @@
package com.alya.ecommerce_serang.data.api.response.store.orders
import com.google.gson.annotations.SerializedName
data class UpdateOrderItemResponse(
@field:SerializedName("message")
val message: String? = null,
@field:SerializedName("updatedOrder")
val updatedOrder: UpdatedOrder? = null,
@field:SerializedName("updatedItems")
val updatedItems: List<UpdatedItemsItem?>? = null
)
data class UpdatedItemsItem(
@field:SerializedName("quantity")
val quantity: Int? = null,
@field:SerializedName("price")
val price: String? = null,
@field:SerializedName("subtotal")
val subtotal: String? = null,
@field:SerializedName("product_id")
val productId: Int? = null,
@field:SerializedName("id")
val id: Int? = null,
@field:SerializedName("order_id")
val orderId: Int? = null
)
data class UpdatedOrder(
@field:SerializedName("auto_canceled_at")
val autoCanceledAt: String? = null,
@field:SerializedName("payment_method_id")
val paymentMethodId: Int? = null,
@field:SerializedName("auto_completed_at")
val autoCompletedAt: String? = null,
@field:SerializedName("updated_at")
val updatedAt: String? = null,
@field:SerializedName("total_amount")
val totalAmount: String? = null,
@field:SerializedName("user_id")
val userId: Int? = null,
@field:SerializedName("address_id")
val addressId: Int? = null,
@field:SerializedName("is_negotiable")
val isNegotiable: Boolean? = null,
@field:SerializedName("created_at")
val createdAt: String? = null,
@field:SerializedName("voucher_id")
val voucherId: Any? = null,
@field:SerializedName("id")
val id: Int? = null,
@field:SerializedName("status")
val status: String? = null
)

View File

@ -1,5 +1,7 @@
package com.alya.ecommerce_serang.data.api.response.product package com.alya.ecommerce_serang.data.api.response.store.product
import com.alya.ecommerce_serang.data.api.dto.Preorder
import com.alya.ecommerce_serang.data.api.dto.Product
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
data class CreateProductResponse( data class CreateProductResponse(
@ -13,15 +15,3 @@ data class CreateProductResponse(
@field:SerializedName("preorder") @field:SerializedName("preorder")
val preorder: Preorder? = null val preorder: Preorder? = null
) )
data class Preorder(
@field:SerializedName("duration")
val duration: Int? = null,
@field:SerializedName("product_id")
val productId: Int? = null,
@field:SerializedName("id")
val id: Int? = null
)

View File

@ -0,0 +1,9 @@
package com.alya.ecommerce_serang.data.api.response.store.product
import com.google.gson.annotations.SerializedName
data class DeleteProductResponse(
@field:SerializedName("message")
val message: String? = null
)

View File

@ -0,0 +1,13 @@
package com.alya.ecommerce_serang.data.api.response.store.product
import com.alya.ecommerce_serang.data.api.dto.Product
import com.google.gson.annotations.SerializedName
data class UpdateProductResponse(
@field:SerializedName("product")
val product: Product? = null,
@field:SerializedName("message")
val message: String? = null
)

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response package com.alya.ecommerce_serang.data.api.response.store.product
import com.alya.ecommerce_serang.data.api.dto.ProductsItem import com.alya.ecommerce_serang.data.api.dto.ProductsItem
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName

View File

@ -9,40 +9,42 @@ import com.alya.ecommerce_serang.data.api.dto.OrderRequestBuy
import com.alya.ecommerce_serang.data.api.dto.OtpRequest import com.alya.ecommerce_serang.data.api.dto.OtpRequest
import com.alya.ecommerce_serang.data.api.dto.RegisterRequest import com.alya.ecommerce_serang.data.api.dto.RegisterRequest
import com.alya.ecommerce_serang.data.api.dto.UpdateCart import com.alya.ecommerce_serang.data.api.dto.UpdateCart
import com.alya.ecommerce_serang.data.api.response.product.CreateProductResponse import com.alya.ecommerce_serang.data.api.response.store.product.CreateProductResponse
import com.alya.ecommerce_serang.data.api.response.ViewStoreProductsResponse import com.alya.ecommerce_serang.data.api.response.store.product.ViewStoreProductsResponse
import okhttp3.MultipartBody import okhttp3.MultipartBody
import okhttp3.RequestBody import okhttp3.RequestBody
import com.alya.ecommerce_serang.data.api.response.auth.LoginResponse import com.alya.ecommerce_serang.data.api.response.auth.LoginResponse
import com.alya.ecommerce_serang.data.api.response.auth.OtpResponse import com.alya.ecommerce_serang.data.api.response.auth.OtpResponse
import com.alya.ecommerce_serang.data.api.response.auth.RegisterResponse 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.customer.cart.AddCartResponse
import com.alya.ecommerce_serang.data.api.response.cart.ListCartResponse import com.alya.ecommerce_serang.data.api.response.customer.cart.ListCartResponse
import com.alya.ecommerce_serang.data.api.response.cart.UpdateCartResponse import com.alya.ecommerce_serang.data.api.response.customer.cart.UpdateCartResponse
import com.alya.ecommerce_serang.data.api.response.order.CourierCostResponse import com.alya.ecommerce_serang.data.api.response.customer.order.CourierCostResponse
import com.alya.ecommerce_serang.data.api.response.order.CreateOrderResponse import com.alya.ecommerce_serang.data.api.response.customer.order.CreateOrderResponse
import com.alya.ecommerce_serang.data.api.response.order.ListCityResponse import com.alya.ecommerce_serang.data.api.response.customer.order.ListCityResponse
import com.alya.ecommerce_serang.data.api.response.order.ListProvinceResponse import com.alya.ecommerce_serang.data.api.response.customer.order.ListProvinceResponse
import com.alya.ecommerce_serang.data.api.response.product.AllProductResponse import com.alya.ecommerce_serang.data.api.response.customer.product.AllProductResponse
import com.alya.ecommerce_serang.data.api.response.product.CategoryResponse import com.alya.ecommerce_serang.data.api.response.customer.product.CategoryResponse
import com.alya.ecommerce_serang.data.api.response.product.DetailStoreProductResponse import com.alya.ecommerce_serang.data.api.response.customer.product.DetailStoreProductResponse
import com.alya.ecommerce_serang.data.api.response.product.ProductResponse import com.alya.ecommerce_serang.data.api.response.customer.product.ProductResponse
import com.alya.ecommerce_serang.data.api.response.product.ReviewProductResponse import com.alya.ecommerce_serang.data.api.response.customer.product.ReviewProductResponse
import com.alya.ecommerce_serang.data.api.response.product.StoreResponse import com.alya.ecommerce_serang.data.api.response.customer.product.StoreResponse
import com.alya.ecommerce_serang.data.api.response.profile.AddressResponse import com.alya.ecommerce_serang.data.api.response.customer.profile.AddressResponse
import com.alya.ecommerce_serang.data.api.response.profile.CreateAddressResponse import com.alya.ecommerce_serang.data.api.response.customer.profile.CreateAddressResponse
import com.alya.ecommerce_serang.data.api.response.profile.ProfileResponse import com.alya.ecommerce_serang.data.api.response.customer.profile.ProfileResponse
import com.alya.ecommerce_serang.data.api.response.store.product.DeleteProductResponse
import com.alya.ecommerce_serang.data.api.response.store.product.UpdateProductResponse
import retrofit2.Call import retrofit2.Call
import retrofit2.Response import retrofit2.Response
import retrofit2.http.Body import retrofit2.http.Body
import retrofit2.http.DELETE
import retrofit2.http.GET import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.HeaderMap
import retrofit2.http.Multipart import retrofit2.http.Multipart
import retrofit2.http.POST import retrofit2.http.POST
import retrofit2.http.Part import retrofit2.http.Part
import retrofit2.http.PUT import retrofit2.http.PUT
import retrofit2.http.Path import retrofit2.http.Path
import retrofit2.http.Query
interface ApiService { interface ApiService {
@POST("registeruser") @POST("registeruser")
@ -126,11 +128,23 @@ interface ApiService {
@Part("duration") duration: RequestBody, @Part("duration") duration: RequestBody,
@Part("category_id") categoryId: RequestBody, @Part("category_id") categoryId: RequestBody,
@Part("status") status: RequestBody, @Part("status") status: RequestBody,
@Part("condition") condition: RequestBody,
@Part image: MultipartBody.Part?, @Part image: MultipartBody.Part?,
@Part sppirt: MultipartBody.Part?, @Part sppirt: MultipartBody.Part?,
@Part halal: MultipartBody.Part? @Part halal: MultipartBody.Part?
): Response<CreateProductResponse> ): Response<CreateProductResponse>
@PUT("store/editproduct/{id}")
suspend fun updateProduct(
@Path("id") productId: Int?,
@Body updatedProduct: Map<String, Any?>
): Response<UpdateProductResponse>
@DELETE("store/deleteproduct/{id}")
suspend fun deleteProduct(
@Path("id") productId: Int
): Response<DeleteProductResponse>
@GET("cart_item") @GET("cart_item")
suspend fun getCart (): Response<ListCartResponse> suspend fun getCart (): Response<ListCartResponse>

View File

@ -2,7 +2,7 @@ package com.alya.ecommerce_serang.data.repository
import android.util.Log import android.util.Log
import com.alya.ecommerce_serang.data.api.dto.Store import com.alya.ecommerce_serang.data.api.dto.Store
import com.alya.ecommerce_serang.data.api.response.product.StoreResponse import com.alya.ecommerce_serang.data.api.response.customer.product.StoreResponse
import com.alya.ecommerce_serang.data.api.retrofit.ApiService import com.alya.ecommerce_serang.data.api.retrofit.ApiService
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException import java.io.IOException

View File

@ -5,16 +5,16 @@ 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.CreateAddressRequest
import com.alya.ecommerce_serang.data.api.dto.OrderRequest 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.OrderRequestBuy
import com.alya.ecommerce_serang.data.api.response.cart.DataItem import com.alya.ecommerce_serang.data.api.response.customer.cart.DataItem
import com.alya.ecommerce_serang.data.api.response.order.CourierCostResponse import com.alya.ecommerce_serang.data.api.response.customer.order.CourierCostResponse
import com.alya.ecommerce_serang.data.api.response.order.CreateOrderResponse import com.alya.ecommerce_serang.data.api.response.customer.order.CreateOrderResponse
import com.alya.ecommerce_serang.data.api.response.order.ListCityResponse import com.alya.ecommerce_serang.data.api.response.customer.order.ListCityResponse
import com.alya.ecommerce_serang.data.api.response.order.ListProvinceResponse import com.alya.ecommerce_serang.data.api.response.customer.order.ListProvinceResponse
import com.alya.ecommerce_serang.data.api.response.product.ProductResponse import com.alya.ecommerce_serang.data.api.response.customer.product.ProductResponse
import com.alya.ecommerce_serang.data.api.response.product.StoreProduct import com.alya.ecommerce_serang.data.api.response.customer.product.StoreProduct
import com.alya.ecommerce_serang.data.api.response.product.StoreResponse import com.alya.ecommerce_serang.data.api.response.customer.product.StoreResponse
import com.alya.ecommerce_serang.data.api.response.profile.AddressResponse import com.alya.ecommerce_serang.data.api.response.customer.profile.AddressResponse
import com.alya.ecommerce_serang.data.api.response.profile.CreateAddressResponse import com.alya.ecommerce_serang.data.api.response.customer.profile.CreateAddressResponse
import com.alya.ecommerce_serang.data.api.retrofit.ApiService import com.alya.ecommerce_serang.data.api.retrofit.ApiService
import retrofit2.Response import retrofit2.Response

View File

@ -3,20 +3,20 @@ package com.alya.ecommerce_serang.data.repository
import android.util.Log import android.util.Log
import com.alya.ecommerce_serang.data.api.dto.CartItem import com.alya.ecommerce_serang.data.api.dto.CartItem
import com.alya.ecommerce_serang.data.api.dto.CategoryItem import com.alya.ecommerce_serang.data.api.dto.CategoryItem
import com.alya.ecommerce_serang.data.api.dto.Preorder
import com.alya.ecommerce_serang.data.api.dto.ProductsItem import com.alya.ecommerce_serang.data.api.dto.ProductsItem
import com.alya.ecommerce_serang.data.api.response.product.CreateProductResponse import com.alya.ecommerce_serang.data.api.response.store.product.CreateProductResponse
import com.alya.ecommerce_serang.data.api.response.cart.AddCartResponse import com.alya.ecommerce_serang.data.api.response.customer.cart.AddCartResponse
import com.alya.ecommerce_serang.data.api.response.product.ProductResponse import com.alya.ecommerce_serang.data.api.response.customer.product.ProductResponse
import com.alya.ecommerce_serang.data.api.response.product.ReviewsItem import com.alya.ecommerce_serang.data.api.response.customer.product.ReviewsItem
import com.alya.ecommerce_serang.data.api.response.product.StoreProduct import com.alya.ecommerce_serang.data.api.response.customer.product.StoreProduct
import com.alya.ecommerce_serang.data.api.response.store.product.UpdateProductResponse
import com.alya.ecommerce_serang.data.api.retrofit.ApiService import com.alya.ecommerce_serang.data.api.retrofit.ApiService
import com.alya.ecommerce_serang.utils.SessionManager
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody import okhttp3.MultipartBody
import okhttp3.RequestBody import okhttp3.RequestBody
import java.io.File
class ProductRepository(private val apiService: ApiService) { class ProductRepository(private val apiService: ApiService) {
suspend fun getAllProducts(): Result<List<ProductsItem>> = suspend fun getAllProducts(): Result<List<ProductsItem>> =
@ -158,9 +158,10 @@ class ProductRepository(private val apiService: ApiService) {
minOrder: Int, minOrder: Int,
weight: Int, weight: Int,
isPreOrder: Boolean, isPreOrder: Boolean,
duration: Int, preorder: Preorder,
categoryId: Int, categoryId: Int,
status: String, status: String,
condition: String,
imagePart: MultipartBody.Part?, imagePart: MultipartBody.Part?,
sppirtPart: MultipartBody.Part?, sppirtPart: MultipartBody.Part?,
halalPart: MultipartBody.Part? halalPart: MultipartBody.Part?
@ -174,9 +175,10 @@ class ProductRepository(private val apiService: ApiService) {
minOrder = RequestBody.create("text/plain".toMediaTypeOrNull(), minOrder.toString()), minOrder = RequestBody.create("text/plain".toMediaTypeOrNull(), minOrder.toString()),
weight = RequestBody.create("text/plain".toMediaTypeOrNull(), weight.toString()), weight = RequestBody.create("text/plain".toMediaTypeOrNull(), weight.toString()),
isPreOrder = RequestBody.create("text/plain".toMediaTypeOrNull(), isPreOrder.toString()), isPreOrder = RequestBody.create("text/plain".toMediaTypeOrNull(), isPreOrder.toString()),
duration = RequestBody.create("text/plain".toMediaTypeOrNull(), duration.toString()), duration = RequestBody.create("text/plain".toMediaTypeOrNull(), preorder.duration.toString()),
categoryId = RequestBody.create("text/plain".toMediaTypeOrNull(), categoryId.toString()), categoryId = RequestBody.create("text/plain".toMediaTypeOrNull(), categoryId.toString()),
status = RequestBody.create("text/plain".toMediaTypeOrNull(), status), status = RequestBody.create("text/plain".toMediaTypeOrNull(), status),
condition = RequestBody.create("text/plain".toMediaTypeOrNull(), condition),
image = imagePart, image = imagePart,
sppirt = sppirtPart, sppirt = sppirtPart,
halal = halalPart halal = halalPart
@ -192,6 +194,31 @@ class ProductRepository(private val apiService: ApiService) {
} }
} }
suspend fun updateProduct(productId: Int?, updatedProduct: Map<String, Any?>) : UpdateProductResponse {
// Build the request with the updated fields
val response = apiService.updateProduct(productId, updatedProduct)
if (response.isSuccessful) {
return response.body()!!
} else {
throw Exception("Gagal memperbarui produk: ${response.code()}")
}
}
suspend fun deleteProduct(productId: Int): Result<Unit> {
return withContext(Dispatchers.IO) {
try {
val response = apiService.deleteProduct(productId)
if (response.isSuccessful) {
Result.Success(Unit)
} else {
Result.Error(Exception("Gagal menghapus produk: ${response.code()}"))
}
} catch (e: Exception) {
Result.Error(e)
}
}
}
companion object { companion object {
private const val TAG = "ProductRepository" private const val TAG = "ProductRepository"

View File

@ -6,7 +6,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.alya.ecommerce_serang.R import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.data.api.dto.CheckoutData import com.alya.ecommerce_serang.data.api.dto.CheckoutData
import com.alya.ecommerce_serang.data.api.response.cart.CartItemsItem import com.alya.ecommerce_serang.data.api.response.customer.cart.CartItemsItem
import com.alya.ecommerce_serang.databinding.ItemOrderProductBinding import com.alya.ecommerce_serang.databinding.ItemOrderProductBinding
import com.alya.ecommerce_serang.databinding.ItemOrderSellerBinding import com.alya.ecommerce_serang.databinding.ItemOrderSellerBinding
import com.bumptech.glide.Glide import com.bumptech.glide.Glide

View File

@ -11,7 +11,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import com.alya.ecommerce_serang.data.api.dto.CheckoutData import com.alya.ecommerce_serang.data.api.dto.CheckoutData
import com.alya.ecommerce_serang.data.api.dto.OrderRequest 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.OrderRequestBuy
import com.alya.ecommerce_serang.data.api.response.product.PaymentInfoItem import com.alya.ecommerce_serang.data.api.response.customer.product.PaymentInfoItem
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
import com.alya.ecommerce_serang.data.repository.OrderRepository import com.alya.ecommerce_serang.data.repository.OrderRepository
import com.alya.ecommerce_serang.databinding.ActivityCheckoutBinding import com.alya.ecommerce_serang.databinding.ActivityCheckoutBinding

View File

@ -8,10 +8,10 @@ import androidx.lifecycle.viewModelScope
import com.alya.ecommerce_serang.data.api.dto.CheckoutData import com.alya.ecommerce_serang.data.api.dto.CheckoutData
import com.alya.ecommerce_serang.data.api.dto.OrderRequest 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.OrderRequestBuy
import com.alya.ecommerce_serang.data.api.response.cart.CartItemsItem import com.alya.ecommerce_serang.data.api.response.customer.cart.CartItemsItem
import com.alya.ecommerce_serang.data.api.response.cart.DataItem import com.alya.ecommerce_serang.data.api.response.customer.cart.DataItem
import com.alya.ecommerce_serang.data.api.response.product.PaymentInfoItem import com.alya.ecommerce_serang.data.api.response.customer.product.PaymentInfoItem
import com.alya.ecommerce_serang.data.api.response.profile.AddressesItem import com.alya.ecommerce_serang.data.api.response.customer.profile.AddressesItem
import com.alya.ecommerce_serang.data.repository.OrderRepository import com.alya.ecommerce_serang.data.repository.OrderRepository
import com.alya.ecommerce_serang.data.repository.Result import com.alya.ecommerce_serang.data.repository.Result
import kotlinx.coroutines.launch import kotlinx.coroutines.launch

View File

@ -4,7 +4,7 @@ import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.alya.ecommerce_serang.R import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.data.api.response.product.PaymentInfoItem import com.alya.ecommerce_serang.data.api.response.customer.product.PaymentInfoItem
import com.alya.ecommerce_serang.databinding.ItemPaymentMethodBinding import com.alya.ecommerce_serang.databinding.ItemPaymentMethodBinding
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.RequestOptions

View File

@ -3,8 +3,8 @@ package com.alya.ecommerce_serang.ui.order
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.alya.ecommerce_serang.data.api.response.order.CourierCostsItem import com.alya.ecommerce_serang.data.api.response.customer.order.CourierCostsItem
import com.alya.ecommerce_serang.data.api.response.order.ServicesItem import com.alya.ecommerce_serang.data.api.response.customer.order.ServicesItem
import com.alya.ecommerce_serang.databinding.ItemShippingOrderBinding import com.alya.ecommerce_serang.databinding.ItemShippingOrderBinding
class ShippingAdapter( class ShippingAdapter(

View File

@ -6,7 +6,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.alya.ecommerce_serang.data.api.dto.CostProduct import com.alya.ecommerce_serang.data.api.dto.CostProduct
import com.alya.ecommerce_serang.data.api.dto.CourierCostRequest import com.alya.ecommerce_serang.data.api.dto.CourierCostRequest
import com.alya.ecommerce_serang.data.api.response.order.CourierCostsItem import com.alya.ecommerce_serang.data.api.response.customer.order.CourierCostsItem
import com.alya.ecommerce_serang.data.repository.OrderRepository import com.alya.ecommerce_serang.data.repository.OrderRepository
import com.alya.ecommerce_serang.data.repository.Result import com.alya.ecommerce_serang.data.repository.Result
import kotlinx.coroutines.launch import kotlinx.coroutines.launch

View File

@ -4,7 +4,7 @@ import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.alya.ecommerce_serang.R import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.data.api.response.cart.CartItemsItem import com.alya.ecommerce_serang.data.api.response.customer.cart.CartItemsItem
import com.alya.ecommerce_serang.databinding.ItemOrderProductBinding import com.alya.ecommerce_serang.databinding.ItemOrderProductBinding
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import java.text.NumberFormat import java.text.NumberFormat

View File

@ -15,8 +15,8 @@ import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
import com.alya.ecommerce_serang.data.api.dto.CreateAddressRequest import com.alya.ecommerce_serang.data.api.dto.CreateAddressRequest
import com.alya.ecommerce_serang.data.api.dto.UserProfile import com.alya.ecommerce_serang.data.api.dto.UserProfile
import com.alya.ecommerce_serang.data.api.response.order.CitiesItem import com.alya.ecommerce_serang.data.api.response.customer.order.CitiesItem
import com.alya.ecommerce_serang.data.api.response.order.ProvincesItem import com.alya.ecommerce_serang.data.api.response.customer.order.ProvincesItem
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
import com.alya.ecommerce_serang.data.api.retrofit.ApiService import com.alya.ecommerce_serang.data.api.retrofit.ApiService
import com.alya.ecommerce_serang.data.repository.OrderRepository import com.alya.ecommerce_serang.data.repository.OrderRepository

View File

@ -5,8 +5,8 @@ import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.alya.ecommerce_serang.data.api.dto.CreateAddressRequest import com.alya.ecommerce_serang.data.api.dto.CreateAddressRequest
import com.alya.ecommerce_serang.data.api.response.order.CitiesItem import com.alya.ecommerce_serang.data.api.response.customer.order.CitiesItem
import com.alya.ecommerce_serang.data.api.response.order.ProvincesItem import com.alya.ecommerce_serang.data.api.response.customer.order.ProvincesItem
import com.alya.ecommerce_serang.data.repository.OrderRepository import com.alya.ecommerce_serang.data.repository.OrderRepository
import com.alya.ecommerce_serang.data.repository.Result import com.alya.ecommerce_serang.data.repository.Result
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow

View File

@ -9,7 +9,7 @@ import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.alya.ecommerce_serang.R import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.data.api.response.profile.AddressesItem import com.alya.ecommerce_serang.data.api.response.customer.profile.AddressesItem
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
class AddressAdapter( class AddressAdapter(

View File

@ -4,7 +4,7 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.alya.ecommerce_serang.data.api.response.profile.AddressesItem import com.alya.ecommerce_serang.data.api.response.customer.profile.AddressesItem
import com.alya.ecommerce_serang.data.repository.OrderRepository import com.alya.ecommerce_serang.data.repository.OrderRepository
import kotlinx.coroutines.launch import kotlinx.coroutines.launch

View File

@ -2,8 +2,8 @@ package com.alya.ecommerce_serang.ui.order.address
import android.content.Context import android.content.Context
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import com.alya.ecommerce_serang.data.api.response.order.CitiesItem import com.alya.ecommerce_serang.data.api.response.customer.order.CitiesItem
import com.alya.ecommerce_serang.data.api.response.order.ProvincesItem import com.alya.ecommerce_serang.data.api.response.customer.order.ProvincesItem
// UI adapters and helpers // UI adapters and helpers
class ProvinceAdapter( class ProvinceAdapter(

View File

@ -16,9 +16,9 @@ import com.alya.ecommerce_serang.BuildConfig.BASE_URL
import com.alya.ecommerce_serang.R import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.data.api.dto.CartItem import com.alya.ecommerce_serang.data.api.dto.CartItem
import com.alya.ecommerce_serang.data.api.dto.ProductsItem import com.alya.ecommerce_serang.data.api.dto.ProductsItem
import com.alya.ecommerce_serang.data.api.response.product.Product import com.alya.ecommerce_serang.data.api.response.customer.product.Product
import com.alya.ecommerce_serang.data.api.response.product.ReviewsItem import com.alya.ecommerce_serang.data.api.response.customer.product.ReviewsItem
import com.alya.ecommerce_serang.data.api.response.product.StoreProduct import com.alya.ecommerce_serang.data.api.response.customer.product.StoreProduct
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
import com.alya.ecommerce_serang.data.api.retrofit.ApiService import com.alya.ecommerce_serang.data.api.retrofit.ApiService
import com.alya.ecommerce_serang.data.repository.ProductRepository import com.alya.ecommerce_serang.data.repository.ProductRepository

View File

@ -7,10 +7,10 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.alya.ecommerce_serang.data.api.dto.CartItem import com.alya.ecommerce_serang.data.api.dto.CartItem
import com.alya.ecommerce_serang.data.api.dto.ProductsItem import com.alya.ecommerce_serang.data.api.dto.ProductsItem
import com.alya.ecommerce_serang.data.api.response.cart.AddCartResponse import com.alya.ecommerce_serang.data.api.response.customer.cart.AddCartResponse
import com.alya.ecommerce_serang.data.api.response.product.Product import com.alya.ecommerce_serang.data.api.response.customer.product.Product
import com.alya.ecommerce_serang.data.api.response.product.ReviewsItem import com.alya.ecommerce_serang.data.api.response.customer.product.ReviewsItem
import com.alya.ecommerce_serang.data.api.response.product.StoreProduct import com.alya.ecommerce_serang.data.api.response.customer.product.StoreProduct
import com.alya.ecommerce_serang.data.repository.ProductRepository import com.alya.ecommerce_serang.data.repository.ProductRepository
import com.alya.ecommerce_serang.data.repository.Result import com.alya.ecommerce_serang.data.repository.Result
import kotlinx.coroutines.launch import kotlinx.coroutines.launch

View File

@ -6,7 +6,7 @@ import android.view.ViewGroup
import android.widget.TextView import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.alya.ecommerce_serang.R import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.data.api.response.product.ReviewsItem import com.alya.ecommerce_serang.data.api.response.customer.product.ReviewsItem
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale import java.util.Locale
import java.util.TimeZone import java.util.TimeZone

View File

@ -36,7 +36,6 @@ class ProductActivity : AppCompatActivity() {
setupHeader() setupHeader()
setupRecyclerView() setupRecyclerView()
observeViewModel() observeViewModel()
binding.progressBar.visibility = View.VISIBLE binding.progressBar.visibility = View.VISIBLE
@ -59,7 +58,7 @@ class ProductActivity : AppCompatActivity() {
} }
is Result.Error -> { is Result.Error -> {
binding.progressBar.visibility = View.GONE binding.progressBar.visibility = View.GONE
Toast.makeText(this, "Failed to load products: ${result.exception.message}", Toast.LENGTH_SHORT).show() Toast.makeText(this, "Gagal memuat produk: ${result.exception.message}", Toast.LENGTH_SHORT).show()
} }
} }
} }
@ -74,7 +73,9 @@ class ProductActivity : AppCompatActivity() {
} }
binding.header.headerRightText.setOnClickListener { binding.header.headerRightText.setOnClickListener {
startActivity(Intent(this, StoreProductDetailActivity::class.java)) val intent = Intent(this, StoreProductDetailActivity::class.java)
intent.putExtra("is_editing", false)
startActivity(intent)
} }
} }

View File

@ -1,13 +1,18 @@
package com.alya.ecommerce_serang.ui.profile.mystore.product package com.alya.ecommerce_serang.ui.profile.mystore.product
import android.app.AlertDialog
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast
import androidx.lifecycle.ViewModelProvider
import com.alya.ecommerce_serang.R import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.data.api.dto.ProductsItem import com.alya.ecommerce_serang.data.api.dto.ProductsItem
import com.alya.ecommerce_serang.databinding.FragmentProductOptionsBottomSheetBinding import com.alya.ecommerce_serang.databinding.FragmentProductOptionsBottomSheetBinding
import com.alya.ecommerce_serang.utils.viewmodel.ProductViewModel
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
class ProductOptionsBottomSheetFragment(private val product: ProductsItem) : BottomSheetDialogFragment() { class ProductOptionsBottomSheetFragment(private val product: ProductsItem) : BottomSheetDialogFragment() {
@ -27,15 +32,25 @@ class ProductOptionsBottomSheetFragment(private val product: ProductsItem) : Bot
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
binding.btnEditProduct.setOnClickListener { binding.btnEditProduct.setOnClickListener {
// Handle editing product val intent = Intent(requireContext(), StoreProductDetailActivity::class.java)
// Example: Open the edit activity or fragment intent.putExtra("product_id", product.id)
intent.putExtra("is_editing", true)
startActivity(intent)
dismiss() dismiss()
} }
binding.btnDeleteProduct.setOnClickListener { binding.btnDeleteProduct.setOnClickListener {
// Handle deleting product AlertDialog.Builder(requireContext())
// Example: Show confirmation dialog .setTitle("Hapus Produk?")
dismiss() .setMessage("Produk yang dihapus tidak dapat dikembalikan.")
.setPositiveButton("Ya, Hapus") { _, _ ->
val viewModel = ViewModelProvider(this).get(ProductViewModel::class.java)
viewModel.deleteProduct(product.id)
Toast.makeText(context, "Produk berhasil dihapus", Toast.LENGTH_SHORT).show()
dismiss()
}
.setNegativeButton("Batalkan", null)
.show()
} }
} }

View File

@ -15,6 +15,8 @@ import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.alya.ecommerce_serang.data.api.dto.CategoryItem import com.alya.ecommerce_serang.data.api.dto.CategoryItem
import com.alya.ecommerce_serang.data.api.dto.Preorder
import com.alya.ecommerce_serang.data.api.dto.Product
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
import com.alya.ecommerce_serang.data.repository.ProductRepository import com.alya.ecommerce_serang.data.repository.ProductRepository
import com.alya.ecommerce_serang.data.repository.Result import com.alya.ecommerce_serang.data.repository.Result
@ -22,12 +24,14 @@ import com.alya.ecommerce_serang.databinding.ActivityStoreProductDetailBinding
import com.alya.ecommerce_serang.utils.viewmodel.ProductViewModel import com.alya.ecommerce_serang.utils.viewmodel.ProductViewModel
import com.alya.ecommerce_serang.utils.BaseViewModelFactory import com.alya.ecommerce_serang.utils.BaseViewModelFactory
import com.alya.ecommerce_serang.utils.SessionManager import com.alya.ecommerce_serang.utils.SessionManager
import com.bumptech.glide.Glide
import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody import okhttp3.MultipartBody
import okhttp3.RequestBody import okhttp3.RequestBody
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import kotlin.getValue import kotlin.getValue
import androidx.core.net.toUri
class StoreProductDetailActivity : AppCompatActivity() { class StoreProductDetailActivity : AppCompatActivity() {
@ -37,6 +41,7 @@ class StoreProductDetailActivity : AppCompatActivity() {
private var imageUri: Uri? = null private var imageUri: Uri? = null
private var sppirtUri: Uri? = null private var sppirtUri: Uri? = null
private var halalUri: Uri? = null private var halalUri: Uri? = null
private var productId: Int? = null
private val viewModel: ProductViewModel by viewModels { private val viewModel: ProductViewModel by viewModels {
BaseViewModelFactory { BaseViewModelFactory {
@ -79,9 +84,50 @@ class StoreProductDetailActivity : AppCompatActivity() {
binding = ActivityStoreProductDetailBinding.inflate(layoutInflater) binding = ActivityStoreProductDetailBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
setupHeader() val isEditing = intent.getBooleanExtra("is_editing", false)
productId = intent.getIntExtra("product_id", -1)
// Fetch categories binding.header.headerTitle.text = if (isEditing) "Ubah Produk" else "Tambah Produk"
// if (isEditing && productId != null) {
// viewModel.productDetail.observe(this) { product ->
// product?.let {
// populateForm(it)
// }
// }
// viewModel.loadProductDetail(productId!!)
// }
setupCategorySpinner()
setupImagePickers()
var conditionList = listOf("Baru", "Pernah Dipakai")
val adapterCondition = ArrayAdapter(this, android.R.layout.simple_spinner_item, conditionList)
adapterCondition.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
binding.spinnerKondisiProduk.adapter = adapterCondition
// Setup Pre-Order visibility
binding.switchIsPreOrder.setOnCheckedChangeListener { _, isChecked ->
binding.layoutDurasi.visibility = if (isChecked) View.VISIBLE else View.GONE
validateForm()
}
validateForm()
binding.btnSaveProduct.setOnClickListener {
if (isEditing) {
updateProduct(productId)
} else {
addProduct()
}
}
binding.header.headerLeftIcon.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
}
private fun setupCategorySpinner() {
viewModel.loadCategories() viewModel.loadCategories()
viewModel.categoryList.observe(this) { result -> viewModel.categoryList.observe(this) { result ->
if (result is Result.Success) { if (result is Result.Success) {
@ -91,13 +137,9 @@ class StoreProductDetailActivity : AppCompatActivity() {
binding.spinnerKategoriProduk.adapter = adapter binding.spinnerKategoriProduk.adapter = adapter
} }
} }
}
// Setup Pre-Order visibility private fun setupImagePickers() {
binding.switchIsPreOrder.setOnCheckedChangeListener { _, isChecked ->
binding.layoutDurasi.visibility = if (isChecked) View.VISIBLE else View.GONE
validateForm()
}
binding.tvTambahFoto.setOnClickListener { binding.tvTambahFoto.setOnClickListener {
val intent = Intent(Intent.ACTION_PICK).apply { type = "image/*" } val intent = Intent(Intent.ACTION_PICK).apply { type = "image/*" }
imagePickerLauncher.launch(intent) imagePickerLauncher.launch(intent)
@ -125,15 +167,37 @@ class StoreProductDetailActivity : AppCompatActivity() {
halalUri = null halalUri = null
binding.switcherHalal.showPrevious() binding.switcherHalal.showPrevious()
} }
}
private fun populateForm(product: Product) {
binding.edtNamaProduk.setText(product.name)
binding.edtDeskripsiProduk.setText(product.description)
binding.edtHargaProduk.setText(product.price.toString())
binding.edtStokProduk.setText(product.stock.toString())
binding.edtMinOrder.setText(product.minOrder.toString())
binding.edtBeratProduk.setText(product.weight.toString())
binding.switchIsPreOrder.isChecked = product.isPreOrder ?: false
binding.switchIsActive.isChecked = product.status == "active"
binding.spinnerKondisiProduk.setSelection(if (product.condition == "Baru") 0 else 1)
product.categoryId?.let {
binding.spinnerKategoriProduk.setSelection(categoryList.indexOfFirst { it.id == product.categoryId })
}
Glide.with(this).load(product.image).into(binding.ivPreviewFoto)
binding.switcherFotoProduk.showNext()
product.sppirt?.let {
binding.tvSppirtName.text = getFileName(it.toUri())
binding.switcherSppirt.showNext()
}
product.halal?.let {
binding.tvHalalName.text = getFileName(it.toUri())
binding.switcherHalal.showNext()
}
validateForm() validateForm()
binding.btnSaveProduct.setOnClickListener {
if (!binding.btnSaveProduct.isEnabled) {
return@setOnClickListener
}
submitProduct()
}
} }
private fun isValidFile(uri: Uri): Boolean { private fun isValidFile(uri: Uri): Boolean {
@ -145,6 +209,36 @@ class StoreProductDetailActivity : AppCompatActivity() {
return uri.lastPathSegment?.split("/")?.last() ?: "unknown_file" return uri.lastPathSegment?.split("/")?.last() ?: "unknown_file"
} }
private fun uriToNamedFile(uri: Uri, context: Context, prefix: String): File {
val extension = context.contentResolver.getType(uri)?.substringAfter("/") ?: "jpg"
val filename = "$prefix-${System.currentTimeMillis()}.$extension"
val file = File(context.cacheDir, filename)
context.contentResolver.openInputStream(uri)?.use { input ->
FileOutputStream(file).use { output -> input.copyTo(output) }
}
return file
}
fun getMimeType(file: File): String {
val extension = file.extension
return when (extension.lowercase()) {
"jpg", "jpeg" -> "image/jpeg"
"png" -> "image/png"
"pdf" -> "application/pdf"
else -> "application/octet-stream"
}
}
fun createPartFromFile(field: String, file: File?): MultipartBody.Part? {
return file?.let {
val mimeType = getMimeType(it).toMediaTypeOrNull()
val requestBody = RequestBody.create(mimeType, it)
MultipartBody.Part.createFormData(field, it.name, requestBody)
}
}
private fun validateForm() { private fun validateForm() {
val valid = binding.edtNamaProduk.text.isNotBlank() && val valid = binding.edtNamaProduk.text.isNotBlank() &&
binding.edtDeskripsiProduk.text.isNotBlank() && binding.edtDeskripsiProduk.text.isNotBlank() &&
@ -164,19 +258,7 @@ class StoreProductDetailActivity : AppCompatActivity() {
) )
} }
private fun uriToNamedFile(uri: Uri, context: Context, prefix: String): File { private fun addProduct() {
val extension = context.contentResolver.getType(uri)?.substringAfter("/") ?: "jpg"
val filename = "$prefix-${System.currentTimeMillis()}.$extension"
val file = File(context.cacheDir, filename)
context.contentResolver.openInputStream(uri)?.use { input ->
FileOutputStream(file).use { output -> input.copyTo(output) }
}
return file
}
private fun submitProduct() {
val name = binding.edtNamaProduk.text.toString() val name = binding.edtNamaProduk.text.toString()
val description = binding.edtDeskripsiProduk.text.toString() val description = binding.edtDeskripsiProduk.text.toString()
val price = binding.edtHargaProduk.text.toString().toInt() val price = binding.edtHargaProduk.text.toString().toInt()
@ -186,6 +268,7 @@ class StoreProductDetailActivity : AppCompatActivity() {
val isPreOrder = binding.switchIsPreOrder.isChecked val isPreOrder = binding.switchIsPreOrder.isChecked
val duration = if (isPreOrder) binding.edtDurasi.text.toString().toInt() else 0 val duration = if (isPreOrder) binding.edtDurasi.text.toString().toInt() else 0
val status = if (binding.switchIsActive.isChecked) "active" else "inactive" val status = if (binding.switchIsActive.isChecked) "active" else "inactive"
val condition = binding.spinnerKondisiProduk.selectedItem.toString()
val categoryId = categoryList.getOrNull(binding.spinnerKategoriProduk.selectedItemPosition)?.id ?: 0 val categoryId = categoryList.getOrNull(binding.spinnerKategoriProduk.selectedItemPosition)?.id ?: 0
val imageFile = imageUri?.let { uriToNamedFile(it, this, "productimg") } val imageFile = imageUri?.let { uriToNamedFile(it, this, "productimg") }
@ -199,8 +282,10 @@ class StoreProductDetailActivity : AppCompatActivity() {
val sppirtPart = sppirtFile?.let { createPartFromFile("sppirt", it) } val sppirtPart = sppirtFile?.let { createPartFromFile("sppirt", it) }
val halalPart = halalFile?.let { createPartFromFile("halal", it) } val halalPart = halalFile?.let { createPartFromFile("halal", it) }
val preorder = Preorder(productId = productId, duration = duration)
viewModel.addProduct( viewModel.addProduct(
name, description, price, stock, minOrder, weight, isPreOrder, duration, categoryId, status, imagePart, sppirtPart, halalPart name, description, price, stock, minOrder, weight, isPreOrder, preorder, categoryId, status, condition, imagePart, sppirtPart, halalPart
) )
viewModel.productCreationResult.observe(this) { result -> viewModel.productCreationResult.observe(this) { result ->
@ -208,7 +293,7 @@ class StoreProductDetailActivity : AppCompatActivity() {
is Result.Loading -> binding.btnSaveProduct.isEnabled = false is Result.Loading -> binding.btnSaveProduct.isEnabled = false
is Result.Success -> { is Result.Success -> {
val product = result.data.product val product = result.data.product
Toast.makeText(this, "Product Created: ${product?.productName}", Toast.LENGTH_SHORT).show() Toast.makeText(this, "Product Created: ${product?.name}", Toast.LENGTH_SHORT).show()
finish() finish()
} }
is Result.Error -> { is Result.Error -> {
@ -219,26 +304,24 @@ class StoreProductDetailActivity : AppCompatActivity() {
} }
} }
fun getMimeType(file: File): String { private fun updateProduct(productId: Int?) {
val extension = file.extension val updatedProduct = mapOf(
return when (extension.lowercase()) { "name" to binding.edtNamaProduk.text.toString(),
"jpg", "jpeg" -> "image/jpeg" "description" to binding.edtDeskripsiProduk.text.toString(),
"png" -> "image/png" "price" to binding.edtHargaProduk.text.toString(),
"pdf" -> "application/pdf" "stock" to binding.edtStokProduk.text.toString().toInt(),
else -> "application/octet-stream" "min_order" to binding.edtMinOrder.text.toString().toInt(),
} "weight" to binding.edtBeratProduk.text.toString().toInt(),
} "is_pre_order" to binding.switchIsPreOrder.isChecked,
"duration" to binding.edtDurasi.text.toString().toInt(),
"category_id" to categoryList[binding.spinnerKategoriProduk.selectedItemPosition].id,
"status" to if (binding.switchIsActive.isChecked) "active" else "inactive",
"condition" to binding.spinnerKondisiProduk.selectedItem.toString(),
"productimg" to imageUri?.path,
"sppirt" to sppirtUri?.path,
"halal" to halalUri?.path
)
fun createPartFromFile(field: String, file: File?): MultipartBody.Part? { viewModel.updateProduct(productId, updatedProduct)
return file?.let {
val mimeType = getMimeType(it).toMediaTypeOrNull()
val requestBody = RequestBody.create(mimeType, it)
MultipartBody.Part.createFormData(field, it.name, requestBody)
}
}
private fun setupHeader() {
binding.header.headerTitle.text = "Tambah Produk"
binding.header.headerLeftIcon.setOnClickListener { onBackPressedDispatcher.onBackPressed() }
} }
} }

View File

@ -5,11 +5,13 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.alya.ecommerce_serang.data.api.dto.CategoryItem import com.alya.ecommerce_serang.data.api.dto.CategoryItem
import com.alya.ecommerce_serang.data.api.dto.Preorder
import com.alya.ecommerce_serang.data.api.dto.ProductsItem import com.alya.ecommerce_serang.data.api.dto.ProductsItem
import com.alya.ecommerce_serang.data.api.response.product.CreateProductResponse import com.alya.ecommerce_serang.data.api.response.store.product.CreateProductResponse
import com.alya.ecommerce_serang.data.api.response.product.Product import com.alya.ecommerce_serang.data.api.response.customer.product.Product
import com.alya.ecommerce_serang.data.api.response.product.ReviewsItem import com.alya.ecommerce_serang.data.api.response.customer.product.ReviewsItem
import com.alya.ecommerce_serang.data.api.response.product.StoreProduct import com.alya.ecommerce_serang.data.api.response.customer.product.StoreProduct
import com.alya.ecommerce_serang.data.api.response.store.product.UpdateProductResponse
import com.alya.ecommerce_serang.data.repository.ProductRepository import com.alya.ecommerce_serang.data.repository.ProductRepository
import com.alya.ecommerce_serang.data.repository.Result import com.alya.ecommerce_serang.data.repository.Result
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -20,6 +22,9 @@ class ProductViewModel(private val repository: ProductRepository) : ViewModel()
private val _productCreationResult = MutableLiveData<Result<CreateProductResponse>>() private val _productCreationResult = MutableLiveData<Result<CreateProductResponse>>()
val productCreationResult: LiveData<Result<CreateProductResponse>> get() = _productCreationResult val productCreationResult: LiveData<Result<CreateProductResponse>> get() = _productCreationResult
private val _productUpdateResult = MutableLiveData<Result<UpdateProductResponse>>()
val productUpdateResult: LiveData<Result<UpdateProductResponse>> get() = _productUpdateResult
private val _productDetail = MutableLiveData<Product?>() private val _productDetail = MutableLiveData<Product?>()
val productDetail: LiveData<Product?> get() = _productDetail val productDetail: LiveData<Product?> get() = _productDetail
@ -49,6 +54,12 @@ class ProductViewModel(private val repository: ProductRepository) : ViewModel()
} }
} }
fun loadPreorderProducts(productId: Int) {
viewModelScope.launch {
}
}
fun loadMyStoreProducts() { fun loadMyStoreProducts() {
viewModelScope.launch { viewModelScope.launch {
_productList.value = Result.Loading _productList.value = Result.Loading
@ -76,9 +87,10 @@ class ProductViewModel(private val repository: ProductRepository) : ViewModel()
minOrder: Int, minOrder: Int,
weight: Int, weight: Int,
isPreOrder: Boolean, isPreOrder: Boolean,
duration: Int, preorder: Preorder,
categoryId: Int, categoryId: Int,
status: String, status: String,
condition: String,
imagePart: MultipartBody.Part?, imagePart: MultipartBody.Part?,
sppirtPart: MultipartBody.Part?, sppirtPart: MultipartBody.Part?,
halalPart: MultipartBody.Part? halalPart: MultipartBody.Part?
@ -86,12 +98,31 @@ class ProductViewModel(private val repository: ProductRepository) : ViewModel()
_productCreationResult.value = Result.Loading _productCreationResult.value = Result.Loading
viewModelScope.launch { viewModelScope.launch {
val result = repository.addProduct( val result = repository.addProduct(
name, description, price, stock, minOrder, weight, isPreOrder, duration, categoryId, status, imagePart, sppirtPart, halalPart name, description, price, stock, minOrder, weight, isPreOrder, preorder, categoryId, status, condition, imagePart, sppirtPart, halalPart
) )
_productCreationResult.value = result _productCreationResult.value = result
} }
} }
fun updateProduct(productId: Int?, updatedProduct: Map<String, Any?>) {
_productUpdateResult.value = Result.Loading
viewModelScope.launch {
try {
val response = repository.updateProduct(productId, updatedProduct)
_productUpdateResult.value = Result.Success(response)
} catch (e: Exception) {
_productUpdateResult.value = Result.Error(e)
}
}
}
fun deleteProduct(productId: Int) {
viewModelScope.launch {
val result = repository.deleteProduct(productId)
// handle the response (loading, success, or error)
}
}
// Optional: for store detail if you need it later // Optional: for store detail if you need it later
// fun loadStoreDetail(storeId: Int) { // fun loadStoreDetail(storeId: Int) {
// viewModelScope.launch { // viewModelScope.launch {

View File

@ -5,6 +5,6 @@
android:id="@+id/main" android:id="@+id/main"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".data.api.response.cart.CartActivity"> tools:context=".data.api.response.customer.cart.CartActivity">
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -481,66 +481,66 @@
</LinearLayout> </LinearLayout>
<!-- &lt;!&ndash; Kondisi Produk &ndash;&gt;--> <!-- Kondisi Produk -->
<!-- <LinearLayout--> <LinearLayout
<!-- android:layout_width="match_parent"--> android:layout_width="match_parent"
<!-- android:layout_height="wrap_content"--> android:layout_height="wrap_content"
<!-- android:orientation="vertical"--> android:orientation="vertical"
<!-- android:layout_marginBottom="24dp">--> android:layout_marginBottom="24dp">
<!-- &lt;!&ndash; Label Kondisi Produk &ndash;&gt;--> <!-- Label Kondisi Produk -->
<!-- <LinearLayout--> <LinearLayout
<!-- android:layout_width="match_parent"--> android:layout_width="match_parent"
<!-- android:layout_height="wrap_content"--> android:layout_height="wrap_content"
<!-- android:orientation="horizontal">--> android:orientation="horizontal">
<!-- <TextView--> <TextView
<!-- android:layout_width="wrap_content"--> android:layout_width="wrap_content"
<!-- android:layout_height="wrap_content"--> android:layout_height="wrap_content"
<!-- android:text="Kondisi Produk"--> android:text="Kondisi Produk"
<!-- style="@style/body_medium"--> style="@style/body_medium"
<!-- android:layout_marginEnd="4dp"/>--> android:layout_marginEnd="4dp"/>
<!-- <TextView--> <TextView
<!-- android:layout_width="0dp"--> android:layout_width="0dp"
<!-- android:layout_height="wrap_content"--> android:layout_height="wrap_content"
<!-- android:layout_weight="1"--> android:layout_weight="1"
<!-- android:text="*"--> android:text="*"
<!-- style="@style/body_medium"--> style="@style/body_medium"
<!-- android:textColor="@color/red_required"--> android:textColor="@color/red_required"
<!-- android:layout_gravity="end"/>--> android:layout_gravity="end"/>
<!-- </LinearLayout>--> </LinearLayout>
<!-- &lt;!&ndash; Spinner Dropdown dengan Chevron &ndash;&gt;--> <!-- Spinner Dropdown dengan Chevron -->
<!-- <LinearLayout--> <LinearLayout
<!-- android:layout_width="match_parent"--> android:layout_width="match_parent"
<!-- android:layout_height="wrap_content"--> android:layout_height="wrap_content"
<!-- android:orientation="horizontal"--> android:orientation="horizontal"
<!-- android:background="@drawable/bg_text_field"--> android:background="@drawable/bg_text_field"
<!-- android:gravity="center_vertical"--> android:gravity="center_vertical"
<!-- android:layout_marginTop="10dp">--> android:layout_marginTop="10dp">
<!-- <Spinner--> <Spinner
<!-- android:id="@+id/spinner_kondisi_produk"--> android:id="@+id/spinner_kondisi_produk"
<!-- android:layout_width="0dp"--> android:layout_width="0dp"
<!-- android:layout_height="wrap_content"--> android:layout_height="wrap_content"
<!-- android:layout_weight="1"--> android:layout_weight="1"
<!-- android:padding="8dp"--> android:padding="8dp"
<!-- style="@style/body_small"--> style="@style/body_small"
<!-- android:background="@null"/>--> android:background="@null"/>
<!-- &lt;!&ndash; Chevron Down Icon &ndash;&gt;--> <!-- Chevron Down Icon -->
<!-- <ImageView--> <ImageView
<!-- android:layout_width="16dp"--> android:layout_width="16dp"
<!-- android:layout_height="16dp"--> android:layout_height="16dp"
<!-- android:src="@drawable/ic_down"--> android:src="@drawable/ic_down"
<!-- android:layout_marginEnd="8dp"--> android:layout_marginEnd="8dp"
<!-- android:contentDescription="Chevron Down" />--> android:contentDescription="Chevron Down" />
<!-- </LinearLayout>--> </LinearLayout>
<!-- </LinearLayout>--> </LinearLayout>
<!-- Pre-Order --> <!-- Pre-Order -->
<LinearLayout <LinearLayout