diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index dd10380..50af9ab 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -58,7 +58,7 @@
android:exported="false" />
+ android:exported="false">
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/UserProfile.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/UserProfile.kt
new file mode 100644
index 0000000..333a2ac
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/dto/UserProfile.kt
@@ -0,0 +1,30 @@
+package com.alya.ecommerce_serang.data.api.dto
+
+import com.google.gson.annotations.SerializedName
+
+data class UserProfile(
+
+ @field:SerializedName("image")
+ val image: Any?,
+
+ @field:SerializedName("role")
+ val role: String,
+
+ @field:SerializedName("user_id")
+ val userId: Int,
+
+ @field:SerializedName("phone")
+ val phone: String,
+
+ @field:SerializedName("birth_date")
+ val birthDate: String,
+
+ @field:SerializedName("name")
+ val name: String,
+
+ @field:SerializedName("email")
+ val email: String,
+
+ @field:SerializedName("username")
+ val username: String
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/ProductResponse.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/ProductResponse.kt
index 26b1130..041a2a4 100644
--- a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/ProductResponse.kt
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/ProductResponse.kt
@@ -35,7 +35,7 @@ data class Product(
val isPreOrder: Boolean,
@field:SerializedName("duration")
- val duration: Any,
+ val duration: Any?,
@field:SerializedName("category_id")
val categoryId: Int,
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/ProfileResponse.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/ProfileResponse.kt
new file mode 100644
index 0000000..d9fe08d
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/ProfileResponse.kt
@@ -0,0 +1,15 @@
+package com.alya.ecommerce_serang.data.api.response
+
+import com.alya.ecommerce_serang.data.api.dto.UserProfile
+import com.google.gson.annotations.SerializedName
+
+data class ProfileResponse(
+
+ @field:SerializedName("message")
+ val message: String,
+
+ @field:SerializedName("user")
+ val user: UserProfile
+)
+
+
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/ReviewProductResponse.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/ReviewProductResponse.kt
new file mode 100644
index 0000000..d7313b5
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/ReviewProductResponse.kt
@@ -0,0 +1,39 @@
+package com.alya.ecommerce_serang.data.api.response
+
+import com.google.gson.annotations.SerializedName
+
+data class ReviewProductResponse(
+
+ @field:SerializedName("reviews")
+ val reviews: List,
+
+ @field:SerializedName("message")
+ val message: String
+)
+
+data class ReviewsItem(
+
+ @field:SerializedName("order_item_id")
+ val orderItemId: Int,
+
+ @field:SerializedName("review_date")
+ val reviewDate: String,
+
+ @field:SerializedName("user_image")
+ val userImage: Any,
+
+ @field:SerializedName("product_id")
+ val productId: Int,
+
+ @field:SerializedName("rating")
+ val rating: Int,
+
+ @field:SerializedName("review_text")
+ val reviewText: String,
+
+ @field:SerializedName("product_name")
+ val productName: String,
+
+ @field:SerializedName("username")
+ val username: String
+)
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 0d4a120..5a2954a 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
@@ -9,6 +9,7 @@ import com.alya.ecommerce_serang.data.api.response.LoginResponse
import com.alya.ecommerce_serang.data.api.response.OtpResponse
import com.alya.ecommerce_serang.data.api.response.ProductResponse
import com.alya.ecommerce_serang.data.api.response.RegisterResponse
+import com.alya.ecommerce_serang.data.api.response.ReviewProductResponse
import com.alya.ecommerce_serang.data.api.response.StoreResponse
import retrofit2.Call
import retrofit2.Response
@@ -40,10 +41,15 @@ interface ApiService {
@GET("product")
suspend fun getAllProduct(): Response
- @GET("product/detail/{id}")
- fun getDetailProduct (
+ @GET("product/review/{id}")
+ suspend fun getProductReview(
@Path("id") productId: Int
- ): Call
+ ): Response
+
+ @GET("product/detail/{id}")
+ suspend fun getDetailProduct (
+ @Path("id") productId: Int
+ ): Response
@GET("mystore")
fun getStore (): Call
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/model/Product.kt b/app/src/main/java/com/alya/ecommerce_serang/data/model/Product.kt
deleted file mode 100644
index a5f79ea..0000000
--- a/app/src/main/java/com/alya/ecommerce_serang/data/model/Product.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.alya.ecommerce_serang.data.model
-
-import com.google.gson.annotations.SerializedName
-
-data class Product(
-
- @field:SerializedName("store_id")
- val storeId: Int,
-
- @field:SerializedName("image")
- val image: String,
-
- @field:SerializedName("rating")
- val rating: String,
-
- @field:SerializedName("description")
- val description: String,
-
- @field:SerializedName("weight")
- val weight: Int,
-
- @field:SerializedName("product_name")
- val productName: String,
-
- @field:SerializedName("is_pre_order")
- val isPreOrder: Boolean,
-
- @field:SerializedName("duration")
- val duration: Any,
-
- @field:SerializedName("category_id")
- val categoryId: Int,
-
- @field:SerializedName("price")
- val price: String,
-
- @field:SerializedName("product_id")
- val productId: Int,
-
- @field:SerializedName("min_order")
- val minOrder: Int,
-
- @field:SerializedName("total_sold")
- val totalSold: Int,
-
- @field:SerializedName("stock")
- val stock: Int,
-
- @field:SerializedName("product_category")
- val productCategory: String
-)
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/repository/ProductRepository.kt b/app/src/main/java/com/alya/ecommerce_serang/data/repository/ProductRepository.kt
index cfe5e8a..dcf5402 100644
--- a/app/src/main/java/com/alya/ecommerce_serang/data/repository/ProductRepository.kt
+++ b/app/src/main/java/com/alya/ecommerce_serang/data/repository/ProductRepository.kt
@@ -3,6 +3,8 @@ package com.alya.ecommerce_serang.data.repository
import android.util.Log
import com.alya.ecommerce_serang.data.api.dto.CategoryItem
import com.alya.ecommerce_serang.data.api.dto.ProductsItem
+import com.alya.ecommerce_serang.data.api.response.ProductResponse
+import com.alya.ecommerce_serang.data.api.response.ReviewsItem
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@@ -29,6 +31,19 @@ class ProductRepository(private val apiService: ApiService) {
}
}
+ suspend fun fetchProductDetail(productId: Int): ProductResponse? {
+ return try {
+ val response = apiService.getDetailProduct(productId)
+ if (response.isSuccessful) {
+ response.body()
+ } else {
+ null
+ }
+ } catch (e: Exception) {
+ null
+ }
+ }
+
suspend fun getAllCategories(): Result> =
withContext(Dispatchers.IO) {
try {
@@ -49,4 +64,17 @@ class ProductRepository(private val apiService: ApiService) {
}
}
+ suspend fun fetchProductReview(productId: Int): List? {
+ return try {
+ val response = apiService.getProductReview(productId)
+ if (response.isSuccessful) {
+ response.body()?.reviews // Ambil daftar review dari response
+ } else {
+ null
+ }
+ } catch (e: Exception) {
+ null
+ }
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/home/HomeFragment.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/home/HomeFragment.kt
index 902ab06..279641c 100644
--- a/app/src/main/java/com/alya/ecommerce_serang/ui/home/HomeFragment.kt
+++ b/app/src/main/java/com/alya/ecommerce_serang/ui/home/HomeFragment.kt
@@ -1,5 +1,6 @@
package com.alya.ecommerce_serang.ui.home
+import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
@@ -18,6 +19,7 @@ import com.alya.ecommerce_serang.data.api.dto.ProductsItem
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
import com.alya.ecommerce_serang.data.repository.ProductRepository
import com.alya.ecommerce_serang.databinding.FragmentHomeBinding
+import com.alya.ecommerce_serang.ui.product.DetailProductActivity
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
import com.alya.ecommerce_serang.utils.HorizontalMarginItemDecoration
import com.alya.ecommerce_serang.utils.SessionManager
@@ -159,7 +161,9 @@ class HomeFragment : Fragment() {
private fun handleProductClick(product: ProductsItem) {
-
+ val intent = Intent(requireContext(), DetailProductActivity::class.java)
+ intent.putExtra("PRODUCT_ID", product.id) // Pass product ID
+ startActivity(intent)
}
private fun handleCategoryProduct(category: CategoryItem) {
diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/product/DetailProductActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/product/DetailProductActivity.kt
index 284f79d..cc5c7ea 100644
--- a/app/src/main/java/com/alya/ecommerce_serang/ui/product/DetailProductActivity.kt
+++ b/app/src/main/java/com/alya/ecommerce_serang/ui/product/DetailProductActivity.kt
@@ -1,21 +1,71 @@
package com.alya.ecommerce_serang.ui.product
import android.os.Bundle
-import androidx.activity.enableEdgeToEdge
+import android.util.Log
+import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
-import androidx.core.view.ViewCompat
-import androidx.core.view.WindowInsetsCompat
-import com.alya.ecommerce_serang.R
+import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
+import com.alya.ecommerce_serang.data.api.retrofit.ApiService
+import com.alya.ecommerce_serang.data.repository.ProductRepository
+import com.alya.ecommerce_serang.databinding.ActivityDetailProductBinding
+import com.alya.ecommerce_serang.ui.home.HomeViewModel
+import com.alya.ecommerce_serang.utils.BaseViewModelFactory
+import com.alya.ecommerce_serang.utils.SessionManager
class DetailProductActivity : AppCompatActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- enableEdgeToEdge()
- setContentView(R.layout.activity_detail_product)
- 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
+ private lateinit var binding: ActivityDetailProductBinding
+ private lateinit var apiService: ApiService
+ private lateinit var sessionManager: SessionManager
+
+ private val viewModel: ProductViewModel by viewModels {
+ BaseViewModelFactory {
+ val apiService = ApiConfig.getApiService(sessionManager)
+ val productRepository = ProductRepository(apiService)
+ HomeViewModel(productRepository)
}
}
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityDetailProductBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ sessionManager = SessionManager(this)
+ apiService = ApiConfig.getApiService(sessionManager)
+
+ val productId = intent.getIntExtra("PRODUCT_ID", -1)
+ if (productId == -1) {
+ Log.e("DetailProductActivity", "Invalid Product ID")
+ finish() // Close activity if no valid ID
+ return
+ }
+
+// 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
+// }
+
+ viewModel.loadProductDetail(productId)
+
+ viewModel.productDetail.observe(this) { product ->
+ if (product != null) {
+ Log.d("ProductDetail", "Name: ${product.productName}, Price: ${product.price}")
+ // Update UI here, e.g., show in a TextView or ImageView
+ binding.tvProductName.text = product.productName
+ binding.tvPrice.text = product.price
+ binding.tvSold.text = product.totalSold.toString()
+ binding.tvRating.text = product.rating
+ binding.tvWeight.text = product.weight.toString()
+ binding.tvStock.text = product.stock.toString()
+ binding.tvCategory.text = product.productCategory
+ binding.tvDescription.text = product.description
+ binding.tvSellerName.text = product.storeId.toString()
+
+
+ } else {
+ Log.e("ProductDetail", "Failed to fetch product details")
+ }
+ }
+
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/product/ProductViewModel.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/product/ProductViewModel.kt
new file mode 100644
index 0000000..f822239
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/ui/product/ProductViewModel.kt
@@ -0,0 +1,22 @@
+package com.alya.ecommerce_serang.ui.product
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.alya.ecommerce_serang.data.api.response.Product
+import com.alya.ecommerce_serang.data.repository.ProductRepository
+import kotlinx.coroutines.launch
+
+class ProductViewModel(private val repository: ProductRepository) : ViewModel() {
+
+ private val _productDetail = MutableLiveData()
+ val productDetail: LiveData get() = _productDetail
+
+ fun loadProductDetail(productId: Int) {
+ viewModelScope.launch {
+ val result = repository.fetchProductDetail(productId)
+ _productDetail.value = result?.product
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/DetailProfileFragment.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/DetailProfileFragment.kt
new file mode 100644
index 0000000..c703316
--- /dev/null
+++ b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/DetailProfileFragment.kt
@@ -0,0 +1,60 @@
+package com.alya.ecommerce_serang.ui.profile
+
+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
+
+// TODO: Rename parameter arguments, choose names that match
+// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
+private const val ARG_PARAM1 = "param1"
+private const val ARG_PARAM2 = "param2"
+
+/**
+ * A simple [Fragment] subclass.
+ * Use the [DetailProfileFragment.newInstance] factory method to
+ * create an instance of this fragment.
+ */
+class DetailProfileFragment : Fragment() {
+ // TODO: Rename and change types of parameters
+ private var param1: String? = null
+ private var param2: String? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ arguments?.let {
+ param1 = it.getString(ARG_PARAM1)
+ param2 = it.getString(ARG_PARAM2)
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ // Inflate the layout for this fragment
+ return inflater.inflate(R.layout.fragment_detail_profile, container, false)
+ }
+
+ companion object {
+ /**
+ * Use this factory method to create a new instance of
+ * this fragment using the provided parameters.
+ *
+ * @param param1 Parameter 1.
+ * @param param2 Parameter 2.
+ * @return A new instance of fragment DetailProfileFragment.
+ */
+ // TODO: Rename and change types and number of parameters
+ @JvmStatic
+ fun newInstance(param1: String, param2: String) =
+ DetailProfileFragment().apply {
+ arguments = Bundle().apply {
+ putString(ARG_PARAM1, param1)
+ putString(ARG_PARAM2, param2)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/baseline_add_24.xml b/app/src/main/res/drawable/baseline_add_24.xml
new file mode 100644
index 0000000..2ae27b8
--- /dev/null
+++ b/app/src/main/res/drawable/baseline_add_24.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/circle_background.xml b/app/src/main/res/drawable/circle_background.xml
new file mode 100644
index 0000000..d99ff1b
--- /dev/null
+++ b/app/src/main/res/drawable/circle_background.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_edit.xml b/app/src/main/res/drawable/ic_edit.xml
new file mode 100644
index 0000000..fab852e
--- /dev/null
+++ b/app/src/main/res/drawable/ic_edit.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_detail_product.xml b/app/src/main/res/layout/activity_detail_product.xml
index 433367a..23bd083 100644
--- a/app/src/main/res/layout/activity_detail_product.xml
+++ b/app/src/main/res/layout/activity_detail_product.xml
@@ -1,208 +1,469 @@
-
-
-
-
+
+ android:layout_height="match_parent"
+ app:layout_behavior="@string/appbar_scrolling_view_behavior">
+
+ android:orientation="vertical">
+
+
+
+
+
+ app:cardElevation="0dp">
-
-
-
-
-
-
-
+ android:padding="16dp">
+ tools:text="Rp65.000" />
+ tools:text="Keripik Ikan Tenggiri" />
-
+ android:layout_marginTop="8dp"
+ android:gravity="center_vertical"
+ android:orientation="horizontal">
-
+
-
+
+
+
+
+
+
-
-
-
-
-
+ android:layout_height="wrap_content"/>
-
+
+ app:cardElevation="0dp">
-
+
-
+
-
+
-
+
+
+
+
+
+
-
-
+
-
+
+ app:cardElevation="0dp">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+ android:backgroundTint="@color/white"
+ app:contentInsetStart="0dp">
+ android:layout_height="56dp"
+ android:orientation="horizontal">
-
+
+
+ android:insetTop="0dp"
+ android:insetBottom="0dp"
+ android:text="@string/add_to_cart"
+ android:textColor="@color/blue_500"
+ app:cornerRadius="4dp"
+ app:icon="@drawable/baseline_add_24"
+ app:iconGravity="textStart"
+ app:iconTint="@color/blue_500"
+ app:strokeColor="@color/blue_500" />
-
+ android:insetTop="0dp"
+ android:insetBottom="0dp"
+ android:text="@string/beli_sekarang"
+ android:textColor="@color/white"
+ app:cornerRadius="4dp" />
-
-
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_detail_profile.xml b/app/src/main/res/layout/activity_detail_profile.xml
index 1bc680d..31bbdb2 100644
--- a/app/src/main/res/layout/activity_detail_profile.xml
+++ b/app/src/main/res/layout/activity_detail_profile.xml
@@ -24,6 +24,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_back_24"
+ android:contentDescription="back"
android:background="?attr/selectableItemBackgroundBorderless"/>
+
+
+
+
+