mirror of
https://github.com/shaulascr/ecommerce_serang.git
synced 2025-08-13 10:42:21 +00:00
add reviews
This commit is contained in:
@ -17,6 +17,9 @@
|
|||||||
android:theme="@style/Theme.Ecommerce_serang"
|
android:theme="@style/Theme.Ecommerce_serang"
|
||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
tools:targetApi="31">
|
tools:targetApi="31">
|
||||||
|
<activity
|
||||||
|
android:name=".ui.product.ReviewProductActivity"
|
||||||
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.profile.mystore.balance.BalanceActivity"
|
android:name=".ui.profile.mystore.balance.BalanceActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
@ -58,8 +61,7 @@
|
|||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.MainActivity"
|
android:name=".ui.MainActivity"
|
||||||
android:exported="false">
|
android:exported="false"></activity>
|
||||||
</activity>
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
@ -20,7 +20,7 @@ data class ReviewsItem(
|
|||||||
val reviewDate: String,
|
val reviewDate: String,
|
||||||
|
|
||||||
@field:SerializedName("user_image")
|
@field:SerializedName("user_image")
|
||||||
val userImage: Any,
|
val userImage: String? = null,
|
||||||
|
|
||||||
@field:SerializedName("product_id")
|
@field:SerializedName("product_id")
|
||||||
val productId: Int,
|
val productId: Int,
|
||||||
|
@ -5,6 +5,7 @@ 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.response.AllProductResponse
|
import com.alya.ecommerce_serang.data.api.response.AllProductResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.CategoryResponse
|
import com.alya.ecommerce_serang.data.api.response.CategoryResponse
|
||||||
|
import com.alya.ecommerce_serang.data.api.response.DetailStoreProductResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.LoginResponse
|
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.OtpResponse
|
||||||
import com.alya.ecommerce_serang.data.api.response.ProductResponse
|
import com.alya.ecommerce_serang.data.api.response.ProductResponse
|
||||||
@ -55,6 +56,11 @@ interface ApiService {
|
|||||||
@GET("profile")
|
@GET("profile")
|
||||||
suspend fun getUserProfile(): Response<ProfileResponse>
|
suspend fun getUserProfile(): Response<ProfileResponse>
|
||||||
|
|
||||||
|
@GET("store/detail/{id}")
|
||||||
|
suspend fun getDetailStore (
|
||||||
|
@Path("id") storeId: Int
|
||||||
|
): Response<DetailStoreProductResponse>
|
||||||
|
|
||||||
|
|
||||||
@GET("mystore")
|
@GET("mystore")
|
||||||
fun getStore (): Call<StoreResponse>
|
fun getStore (): Call<StoreResponse>
|
||||||
|
@ -23,6 +23,7 @@ class ProductRepository(private val apiService: ApiService) {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Return a Result.Error with a custom Exception
|
// Return a Result.Error with a custom Exception
|
||||||
|
Log.e("ProductRepository", "Error: ${response.errorBody()?.string()}")
|
||||||
Result.Error(Exception("Failed to fetch products. Code: ${response.code()}"))
|
Result.Error(Exception("Failed to fetch products. Code: ${response.code()}"))
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@ -78,5 +79,19 @@ class ProductRepository(private val apiService: ApiService) {
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// suspend fun fetchStoreDetail(storeId: Int): Store? {
|
||||||
|
// return try {
|
||||||
|
// val response = apiService.getStore(storeId)
|
||||||
|
// if (response.isSucessful) {
|
||||||
|
// response.body()?.store
|
||||||
|
// } else {
|
||||||
|
// Log.e("ProductRepository", "Error: ${response.errorBody()?.string()}")
|
||||||
|
//
|
||||||
|
// null
|
||||||
|
// }
|
||||||
|
// } catch (e: Exception) {
|
||||||
|
// null
|
||||||
|
// }
|
||||||
|
// }
|
@ -1,16 +1,21 @@
|
|||||||
package com.alya.ecommerce_serang.ui.product
|
package com.alya.ecommerce_serang.ui.product
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.alya.ecommerce_serang.BuildConfig.BASE_URL
|
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.ProductsItem
|
||||||
import com.alya.ecommerce_serang.data.api.response.Product
|
import com.alya.ecommerce_serang.data.api.response.Product
|
||||||
|
import com.alya.ecommerce_serang.data.api.response.ReviewsItem
|
||||||
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
|
||||||
import com.alya.ecommerce_serang.databinding.ActivityDetailProductBinding
|
import com.alya.ecommerce_serang.databinding.ActivityDetailProductBinding
|
||||||
|
import com.alya.ecommerce_serang.ui.home.HorizontalProductAdapter
|
||||||
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 com.bumptech.glide.Glide
|
||||||
@ -19,6 +24,8 @@ class DetailProductActivity : AppCompatActivity() {
|
|||||||
private lateinit var binding: ActivityDetailProductBinding
|
private lateinit var binding: ActivityDetailProductBinding
|
||||||
private lateinit var apiService: ApiService
|
private lateinit var apiService: ApiService
|
||||||
private lateinit var sessionManager: SessionManager
|
private lateinit var sessionManager: SessionManager
|
||||||
|
private var productAdapter: HorizontalProductAdapter? = null
|
||||||
|
private var reviewsAdapter: ReviewsAdapter? = null
|
||||||
|
|
||||||
private val viewModel: ProductViewModel by viewModels {
|
private val viewModel: ProductViewModel by viewModels {
|
||||||
BaseViewModelFactory {
|
BaseViewModelFactory {
|
||||||
@ -36,19 +43,15 @@ class DetailProductActivity : AppCompatActivity() {
|
|||||||
apiService = ApiConfig.getApiService(sessionManager)
|
apiService = ApiConfig.getApiService(sessionManager)
|
||||||
|
|
||||||
val productId = intent.getIntExtra("PRODUCT_ID", -1)
|
val productId = intent.getIntExtra("PRODUCT_ID", -1)
|
||||||
|
//nanti tambah get store id dari HomeFragment Product.storeId
|
||||||
if (productId == -1) {
|
if (productId == -1) {
|
||||||
Log.e("DetailProductActivity", "Invalid Product ID")
|
Log.e("DetailProductActivity", "Invalid Product ID")
|
||||||
finish() // Close activity if no valid ID
|
finish() // Close activity if no valid ID
|
||||||
return
|
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.loadProductDetail(productId)
|
||||||
|
viewModel.loadReviews(productId)
|
||||||
|
|
||||||
viewModel.productDetail.observe(this) { product ->
|
viewModel.productDetail.observe(this) { product ->
|
||||||
if (product != null) {
|
if (product != null) {
|
||||||
@ -61,6 +64,7 @@ class DetailProductActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
observeProductDetail()
|
observeProductDetail()
|
||||||
|
observeProductReviews()
|
||||||
}
|
}
|
||||||
private fun observeProductDetail() {
|
private fun observeProductDetail() {
|
||||||
viewModel.productDetail.observe(this) { product ->
|
viewModel.productDetail.observe(this) { product ->
|
||||||
@ -68,6 +72,12 @@ class DetailProductActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun observeProductReviews() {
|
||||||
|
viewModel.reviewProduct.observe(this) { reviews ->
|
||||||
|
setupRecyclerViewReviewsProduct(reviews)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateUI(product: Product){
|
private fun updateUI(product: Product){
|
||||||
binding.tvProductName.text = product.productName
|
binding.tvProductName.text = product.productName
|
||||||
binding.tvPrice.text = product.price
|
binding.tvPrice.text = product.price
|
||||||
@ -79,6 +89,10 @@ class DetailProductActivity : AppCompatActivity() {
|
|||||||
binding.tvDescription.text = product.description
|
binding.tvDescription.text = product.description
|
||||||
binding.tvSellerName.text = product.storeId.toString()
|
binding.tvSellerName.text = product.storeId.toString()
|
||||||
|
|
||||||
|
binding.tvViewAllReviews.setOnClickListener{
|
||||||
|
handleAllReviewsClick(product.productId)
|
||||||
|
}
|
||||||
|
|
||||||
val fullImageUrl = when (val img = product.image) {
|
val fullImageUrl = when (val img = product.image) {
|
||||||
is String -> {
|
is String -> {
|
||||||
if (img.startsWith("/")) BASE_URL + img.substring(1) else img
|
if (img.startsWith("/")) BASE_URL + img.substring(1) else img
|
||||||
@ -91,5 +105,52 @@ class DetailProductActivity : AppCompatActivity() {
|
|||||||
.load(fullImageUrl)
|
.load(fullImageUrl)
|
||||||
.placeholder(R.drawable.placeholder_image)
|
.placeholder(R.drawable.placeholder_image)
|
||||||
.into(binding.ivProductImage)
|
.into(binding.ivProductImage)
|
||||||
|
|
||||||
|
setupRecyclerViewOtherProducts()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleAllReviewsClick(productId: Int) {
|
||||||
|
val intent = Intent(this, ReviewProductActivity::class.java)
|
||||||
|
intent.putExtra("PRODUCT_ID", productId) // Pass product ID
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupRecyclerViewOtherProducts(){
|
||||||
|
productAdapter = HorizontalProductAdapter(
|
||||||
|
products = emptyList(),
|
||||||
|
onClick = { productsItem -> handleProductClick(productsItem) }
|
||||||
|
)
|
||||||
|
|
||||||
|
binding.recyclerViewOtherProducts.apply {
|
||||||
|
adapter = productAdapter
|
||||||
|
layoutManager = LinearLayoutManager(
|
||||||
|
context,
|
||||||
|
LinearLayoutManager.HORIZONTAL,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupRecyclerViewReviewsProduct(reviewList: List<ReviewsItem>){
|
||||||
|
val limitedReviewList = if (reviewList.isNotEmpty()) listOf(reviewList.first()) else emptyList()
|
||||||
|
|
||||||
|
reviewsAdapter = ReviewsAdapter(
|
||||||
|
reviewList = limitedReviewList
|
||||||
|
)
|
||||||
|
|
||||||
|
binding.recyclerViewReviews.apply {
|
||||||
|
adapter = reviewsAdapter
|
||||||
|
layoutManager = LinearLayoutManager(
|
||||||
|
context,
|
||||||
|
LinearLayoutManager.VERTICAL,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleProductClick(product: ProductsItem) {
|
||||||
|
val intent = Intent(this, DetailProductActivity::class.java)
|
||||||
|
intent.putExtra("PRODUCT_ID", product.id) // Pass product ID
|
||||||
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,6 +5,8 @@ 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.Product
|
import com.alya.ecommerce_serang.data.api.response.Product
|
||||||
|
import com.alya.ecommerce_serang.data.api.response.ReviewsItem
|
||||||
|
import com.alya.ecommerce_serang.data.api.response.Store
|
||||||
import com.alya.ecommerce_serang.data.repository.ProductRepository
|
import com.alya.ecommerce_serang.data.repository.ProductRepository
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@ -13,10 +15,30 @@ class ProductViewModel(private val repository: ProductRepository) : ViewModel()
|
|||||||
private val _productDetail = MutableLiveData<Product?>()
|
private val _productDetail = MutableLiveData<Product?>()
|
||||||
val productDetail: LiveData<Product?> get() = _productDetail
|
val productDetail: LiveData<Product?> get() = _productDetail
|
||||||
|
|
||||||
|
private val _storeDetail = MutableLiveData<Store?>()
|
||||||
|
val storeDetail : LiveData<Store?> get() = _storeDetail
|
||||||
|
|
||||||
|
private val _reviewProduct = MutableLiveData<List<ReviewsItem>>()
|
||||||
|
val reviewProduct: LiveData<List<ReviewsItem>> get() = _reviewProduct
|
||||||
|
|
||||||
fun loadProductDetail(productId: Int) {
|
fun loadProductDetail(productId: Int) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val result = repository.fetchProductDetail(productId)
|
val result = repository.fetchProductDetail(productId)
|
||||||
_productDetail.value = result?.product
|
_productDetail.value = result?.product
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun loadReviews(productId: Int) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
val reviews = repository.fetchProductReview(productId)
|
||||||
|
_reviewProduct.value = reviews ?: emptyList()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fun loadStoreDetail(storeId: Int){
|
||||||
|
// viewModelScope.launch {
|
||||||
|
// val storeResult = repository.fetchStoreDetail(storeId)
|
||||||
|
// _storeDetail.value = storeResult
|
||||||
|
// }
|
||||||
|
// }
|
@ -0,0 +1,79 @@
|
|||||||
|
package com.alya.ecommerce_serang.ui.product
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.View
|
||||||
|
import androidx.activity.enableEdgeToEdge
|
||||||
|
import androidx.activity.viewModels
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
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.ActivityReviewProductBinding
|
||||||
|
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
||||||
|
import com.alya.ecommerce_serang.utils.SessionManager
|
||||||
|
|
||||||
|
class ReviewProductActivity : AppCompatActivity() {
|
||||||
|
private lateinit var binding: ActivityReviewProductBinding
|
||||||
|
private lateinit var apiService: ApiService
|
||||||
|
private var reviewsAdapter: ReviewsAdapter? = null
|
||||||
|
private lateinit var sessionManager: SessionManager
|
||||||
|
private val viewModel: ProductViewModel by viewModels {
|
||||||
|
BaseViewModelFactory {
|
||||||
|
val apiService = ApiConfig.getApiService(sessionManager)
|
||||||
|
val productRepository = ProductRepository(apiService)
|
||||||
|
ProductViewModel(productRepository)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
binding = ActivityReviewProductBinding.inflate(layoutInflater)
|
||||||
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
enableEdgeToEdge()
|
||||||
|
|
||||||
|
sessionManager = SessionManager(this)
|
||||||
|
apiService = ApiConfig.getApiService(sessionManager)
|
||||||
|
|
||||||
|
val productId = intent.getIntExtra("PRODUCT_ID", -1) // Get the product ID
|
||||||
|
if (productId == -1) {
|
||||||
|
Log.e("ReviewProductActivity", "Invalid Product ID")
|
||||||
|
finish() // Close the activity if the product ID is invalid
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setupRecyclerView()
|
||||||
|
viewModel.loadReviews(productId) // Fetch reviews using productId
|
||||||
|
|
||||||
|
observeReviews() // Observe review data
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun observeReviews() {
|
||||||
|
viewModel.reviewProduct.observe(this) { reviews ->
|
||||||
|
if (reviews.isNotEmpty()) {
|
||||||
|
reviewsAdapter?.setReviews(reviews)
|
||||||
|
binding.tvNoReviews.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
binding.tvNoReviews.visibility = View.VISIBLE // Show "No Reviews" message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupRecyclerView() {
|
||||||
|
reviewsAdapter = ReviewsAdapter(
|
||||||
|
reviewList = emptyList()
|
||||||
|
)
|
||||||
|
|
||||||
|
binding.rvReviewsProduct.apply {
|
||||||
|
adapter = reviewsAdapter
|
||||||
|
layoutManager = LinearLayoutManager(
|
||||||
|
context,
|
||||||
|
LinearLayoutManager.VERTICAL,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package com.alya.ecommerce_serang.ui.product
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.alya.ecommerce_serang.R
|
||||||
|
import com.alya.ecommerce_serang.data.api.response.ReviewsItem
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Locale
|
||||||
|
import java.util.TimeZone
|
||||||
|
|
||||||
|
class ReviewsAdapter(
|
||||||
|
private var reviewList: List<ReviewsItem>
|
||||||
|
) : RecyclerView.Adapter<ReviewsAdapter.ReviewViewHolder>() {
|
||||||
|
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ReviewViewHolder {
|
||||||
|
val view = LayoutInflater.from(parent.context)
|
||||||
|
.inflate(R.layout.item_review, parent, false)
|
||||||
|
return ReviewViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ReviewViewHolder, position: Int) {
|
||||||
|
val review = reviewList[position]
|
||||||
|
|
||||||
|
with(holder) {
|
||||||
|
tvReviewerName.text = review.username
|
||||||
|
tvReviewRating.text = review.rating.toString()
|
||||||
|
tvReviewText.text = review.reviewText
|
||||||
|
tvDateReview.text = formatDate(review.reviewDate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = reviewList.size
|
||||||
|
|
||||||
|
fun setReviews(reviews: List<ReviewsItem>) {
|
||||||
|
reviewList = reviews
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun formatDate(dateString: String): String {
|
||||||
|
return try {
|
||||||
|
val inputFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault()) //from json
|
||||||
|
inputFormat.timeZone = TimeZone.getTimeZone("UTC") //get timezone
|
||||||
|
val outputFormat = SimpleDateFormat("dd MMMM yyyy", Locale.getDefault()) // new format
|
||||||
|
val date = inputFormat.parse(dateString) // Parse from json format
|
||||||
|
outputFormat.format(date!!) // convert to new format
|
||||||
|
} catch (e: Exception) {
|
||||||
|
dateString // Return original if error occurs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ReviewViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
val tvReviewRating: TextView = itemView.findViewById(R.id.tvReviewRating)
|
||||||
|
val tvReviewerName: TextView = itemView.findViewById(R.id.tvUsername)
|
||||||
|
val tvReviewText: TextView = itemView.findViewById(R.id.tvReviewText)
|
||||||
|
val tvDateReview: TextView = itemView.findViewById(R.id.date_review)
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,7 @@
|
|||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent">
|
app:layout_constraintEnd_toEndOf="parent">
|
||||||
|
63
app/src/main/res/layout/activity_review_product.xml
Normal file
63
app/src/main/res/layout/activity_review_product.xml
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/main"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".ui.product.ReviewProductActivity">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/topAppBar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:theme="@style/ThemeOverlay.AppCompat.DayNight.ActionBar"
|
||||||
|
android:popupTheme="@style/ThemeOverlay.AppCompat.Light"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/btn_back"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/ic_back_24"
|
||||||
|
android:contentDescription="back"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_review_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Ulasan Produk"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:fontFamily="@font/dmsans_bold"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_gravity="center"/>
|
||||||
|
</androidx.appcompat.widget.Toolbar>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rv_reviews_product"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/topAppBar"
|
||||||
|
tools:itemCount="5"
|
||||||
|
tools:listitem="@layout/item_review" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_no_reviews"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:text="Tidak Ada Ulasan"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/rv_reviews_product"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"/>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -50,6 +50,14 @@
|
|||||||
android:textColor="@color/black" />
|
android:textColor="@color/black" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/date_review"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/dmsans_light"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:textColor="@color/soft_gray"
|
||||||
|
android:text="22-03-2025"/>
|
||||||
<!-- Review Text -->
|
<!-- Review Text -->
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvReviewText"
|
android:id="@+id/tvReviewText"
|
||||||
|
Reference in New Issue
Block a user