detail product

This commit is contained in:
shaulascr
2025-03-25 03:08:06 +07:00
parent 205205059d
commit 733b5293eb
23 changed files with 815 additions and 219 deletions

View File

@ -58,7 +58,7 @@
android:exported="false" />
<activity
android:name=".ui.MainActivity"
android:exported="true">
android:exported="false">
</activity>
</application>

View File

@ -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
)

View File

@ -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,

View File

@ -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
)

View File

@ -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<ReviewsItem>,
@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
)

View File

@ -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<AllProductResponse>
@GET("product/detail/{id}")
fun getDetailProduct (
@GET("product/review/{id}")
suspend fun getProductReview(
@Path("id") productId: Int
): Call<ProductResponse>
): Response<ReviewProductResponse>
@GET("product/detail/{id}")
suspend fun getDetailProduct (
@Path("id") productId: Int
): Response<ProductResponse>
@GET("mystore")
fun getStore (): Call<StoreResponse>

View File

@ -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
)

View File

@ -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<List<CategoryItem>> =
withContext(Dispatchers.IO) {
try {
@ -49,4 +64,17 @@ class ProductRepository(private val apiService: ApiService) {
}
}
suspend fun fetchProductReview(productId: Int): List<ReviewsItem>? {
return try {
val response = apiService.getProductReview(productId)
if (response.isSuccessful) {
response.body()?.reviews // Ambil daftar review dari response
} else {
null
}
} catch (e: Exception) {
null
}
}
}

View File

@ -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) {

View File

@ -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")
}
}
}
}

View File

@ -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<Product?>()
val productDetail: LiveData<Product?> get() = _productDetail
fun loadProductDetail(productId: Int) {
viewModelScope.launch {
val result = repository.fetchProductDetail(productId)
_productDetail.value = result?.product
}
}
}

View File

@ -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)
}
}
}
}

View File

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</vector>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@android:color/white"/>
<stroke
android:width="3dp"
android:color="@color/blue_500" />
<size android:width="40dp" android:height="40dp"/>
</shape>

View File

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#211E1E" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
</vector>

View File

@ -1,208 +1,469 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.coordinatorlayout.widget.CoordinatorLayout
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"
android:background="@color/white"
tools:context=".ui.product.DetailProductActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/white"
app:titleTextColor="@android:color/black"
app:navigationIcon="@drawable/ic_back_24"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:title="Detail Produk" />
<!-- Main Content with Scroll -->
<!-- Main Content -->
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="60dp"
android:fillViewport="true"
app:layout_constraintTop_toBottomOf="@id/toolbar"
app:layout_constraintBottom_toTopOf="@id/bottom_buttons">
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
android:orientation="vertical">
<include
android:id="@+id/searchContainer"
layout="@layout/view_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:layout_constraintTop_toTopOf="parent" />
<!-- Product Image -->
<ImageView
android:id="@+id/ivProductImage"
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="centerCrop"
android:contentDescription="@string/product_image"
tools:src="@drawable/placeholder_image" />
<!-- Product Price and Name -->
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="8dp"
app:cardElevation="4dp">
app:cardElevation="0dp">
<ImageView
android:id="@+id/imgProduct"
android:layout_width="match_parent"
android:layout_height="220dp"
android:scaleType="centerCrop"
android:src="@drawable/placeholder_image" />
</androidx.cardview.widget.CardView>
<!-- Product Info -->
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
app:cardCornerRadius="8dp"
app:cardElevation="4dp"
android:padding="12dp">
<!-- Sold & Rating -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="4dp">
android:padding="16dp">
<TextView
android:id="@+id/tvProductPrice"
android:id="@+id/tvPrice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Rp65.000"
android:textColor="@color/black"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="@color/black" />
tools:text="Rp65.000" />
<TextView
android:id="@+id/tvProductName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Keripik Ikan Tenggiri"
android:layout_marginTop="4dp"
android:textColor="@color/black"
android:textSize="16sp"
android:textColor="@color/black" />
tools:text="Keripik Ikan Tenggiri" />
<TextView
android:id="@+id/tvSold"
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Terjual 10 buah"
android:textColor="@color/gray_1" />
android:layout_marginTop="8dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginStart="8dp"
android:src="@drawable/baseline_star_24" />
<TextView
android:id="@+id/tvSold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/soft_gray"
android:textSize="14sp"
tools:text="@string/item_sold" />
<TextView
android:id="@+id/tvRating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="4.5"
android:textColor="@color/black" />
<View
android:layout_width="16dp"
android:layout_height="0dp" />
<ImageView
android:id="@+id/star_product"
android:layout_width="16dp"
android:layout_height="16dp"
android:contentDescription="@string/rating"
android:src="@drawable/baseline_star_24"/>
<TextView
android:id="@+id/tvRating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:textSize="14sp"
tools:text="4.5" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- Buyer Reviews -->
<TextView
android:text="Ulasan Pembeli"
android:textSize="16sp"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvReviews"
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="false" />
android:layout_height="wrap_content"/>
<!-- Product Details -->
<!-- Buyer Reviews Section -->
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
app:cardCornerRadius="8dp"
app:cardElevation="4dp"
android:padding="12dp">
app:cardElevation="0dp">
<TextView
android:text="Detail Produk"
android:textSize="16sp"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:text="Berat: 200 gram"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:text="Stok: 100 buah"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/ulasan_pembeli"
android:textColor="@color/black"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:text="Kategori: Makanan Ringan"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tvViewAllReviews"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/lihat_semua"
android:textColor="@color/blue_500"
android:textSize="14sp" />
</LinearLayout>
<!-- RecyclerView for Reviews -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerViewReviews"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="1"
tools:listitem="@layout/item_review" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- Related Products -->
<TextView
android:text="Produk lainnya"
android:textSize="16sp"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp" />
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvRelatedProducts"
<!-- Product Details Section -->
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:nestedScrollingEnabled="false" />
app:cardElevation="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/detail_produk"
android:textColor="@color/black"
android:textSize="16sp"
android:textStyle="bold" />
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp">
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/berat_produk"
android:fontFamily="@font/dmsans_semibold"
android:textSize="14sp" />
<TextView
android:id="@+id/tvWeight"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@color/blue_500"
android:textSize="14sp"
tools:text="200 gram" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/stock_product"
android:fontFamily="@font/dmsans_semibold"
android:textSize="14sp" />
<TextView
android:id="@+id/tvStock"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@color/blue_500"
android:textSize="14sp"
tools:text="100 buah" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/kategori"
android:fontFamily="@font/dmsans_semibold"
android:textSize="14sp" />
<TextView
android:id="@+id/tvCategory"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@color/blue_500"
android:textSize="14sp"
tools:text="Makanan Ringan" />
</TableRow>
</TableLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/deskripsi_produk"
android:textColor="@color/black"
android:textSize="16sp"
android:layout_marginTop="8dp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textColor="@color/black"
android:textSize="14sp"
tools:text="Terbuat dari tepung dan ikan tenggiri asli Serang Banten. Tahan selama 25 hari." />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- Product Description Section -->
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="0dp">
</androidx.cardview.widget.CardView>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<!-- Seller Info Section -->
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/ivSellerImage"
android:layout_width="48dp"
android:layout_height="48dp"
android:contentDescription="@string/seller_image"
tools:src="@drawable/placeholder_image" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:orientation="vertical">
<TextView
android:id="@+id/tvSellerName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:textSize="16sp"
android:textStyle="bold"
tools:text="SnackEnak" />
<TextView
android:id="@+id/tvSellerLocation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/dmsans_semibold"
android:textSize="14sp"
tools:text="Jakarta Selatan" />
<RatingBar
android:id="@+id/ratingBarSeller"
style="?android:attr/ratingBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:isIndicator="true"
android:numStars="5"
android:rating="5"
android:stepSize="0.1" />
<TextView
android:id="@+id/tvSellerRating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:textSize="14sp"
android:textStyle="bold"
tools:text="5.0" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<!-- Other Products Section -->
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/produk_lainnya"
android:textColor="@color/black"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvViewAllProducts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/lihat_semua"
android:textColor="@color/blue_500"
android:textSize="14sp" />
</LinearLayout>
<!-- RecyclerView for Other Products -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerViewOtherProducts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="3"
tools:listitem="@layout/item_related_product" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- Bottom spacing -->
<View
android:layout_width="match_parent"
android:layout_height="80dp" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<!-- Fixed Bottom Buttons -->
<FrameLayout
android:id="@+id/bottom_buttons"
<!-- Bottom Action Bar -->
<com.google.android.material.bottomappbar.BottomAppBar
android:id="@+id/bottomAppBar"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="@color/white"
app:layout_constraintBottom_toBottomOf="parent">
android:backgroundTint="@color/white"
app:contentInsetStart="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:gravity="center_vertical"
android:padding="12dp">
android:layout_height="56dp"
android:orientation="horizontal">
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/btnChat"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="48dp"
android:layout_height="match_parent"
android:layout_margin="4dp"
android:insetTop="0dp"
android:insetBottom="0dp"
app:cornerRadius="4dp"
app:icon="@drawable/baseline_chat_24"
android:text="chat"
app:iconGravity="end"
app:iconTint="@color/blue_500" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnAddToCart"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:layout_margin="4dp"
android:layout_weight="1"
android:text="Keranjang"
android:backgroundTint="@color/soft_gray"
android:textColor="@color/black" />
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" />
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/btnBuyNow"
style="@style/Widget.MaterialComponents.Button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:layout_margin="4dp"
android:layout_weight="1"
android:text="Beli Sekarang"
android:backgroundTint="@color/blue_500"
android:textColor="@color/white" />
android:insetTop="0dp"
android:insetBottom="0dp"
android:text="@string/beli_sekarang"
android:textColor="@color/white"
app:cornerRadius="4dp" />
</LinearLayout>
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.bottomappbar.BottomAppBar>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -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"/>
<TextView
@ -54,6 +55,7 @@
android:layout_height="wrap_content"
android:padding="16dp">
<!-- Profile Image -->
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/profile_image"
android:layout_width="100dp"
@ -63,6 +65,21 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<!-- Edit Icon -->
<ImageView
android:id="@+id/edit_icon"
android:layout_width="32dp"
android:layout_height="32dp"
android:src="@drawable/ic_edit"
android:background="@drawable/circle_background"
android:padding="8dp"
app:layout_constraintBottom_toBottomOf="@id/profile_image"
app:layout_constraintEnd_toEndOf="@id/profile_image"
android:layout_marginBottom="4dp"
android:layout_marginEnd="4dp"
app:tint="@color/blue_500" />
<!-- Edit Profile Button -->
<Button
android:id="@+id/btn_ubah_profil"
android:layout_width="wrap_content"
@ -75,6 +92,7 @@
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
<com.google.android.material.textfield.TextInputLayout

View File

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.profile.DetailProfileFragment">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_nama"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:layout_marginHorizontal="16dp"
app:layout_constraintTop_toBottomOf="@id/card_profile">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Nama"
android:text="@string/users_name"
android:enabled="false"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginHorizontal="16dp"
app:layout_constraintTop_toBottomOf="@id/til_nama">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Username"
android:text="@string/username_profile"
android:enabled="false"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@id/til_username">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Email"
android:text="@string/users_email"
android:enabled="false"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_nomor_handphone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginHorizontal="16dp"
app:layout_constraintTop_toBottomOf="@id/til_email">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Nomor Handphone"
android:text="@string/phone_number"
android:enabled="false"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_tanggal_lahir"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginHorizontal="16dp"
app:layout_constraintTop_toBottomOf="@id/til_nomor_handphone">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Tanggal Lahir"
android:text="@string/date_birth"
android:enabled="false"/>
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>

View File

@ -20,7 +20,7 @@
layout="@layout/view_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="19dp"
android:layout_marginTop="16dp"
app:layout_constraintTop_toTopOf="parent" />
<ProgressBar
@ -39,12 +39,11 @@
android:id="@+id/banners"
android:layout_width="match_parent"
android:layout_height="132dp"
android:layout_marginTop="23dp"
android:layout_marginTop="4dp"
android:orientation="vertical"
app:layout_constraintTop_toBottomOf="@id/searchContainer"
tools:layout_editor_absoluteX="16dp" />
<TextView
android:id="@+id/categoriesText"
android:layout_width="wrap_content"

View File

@ -13,15 +13,6 @@
android:orientation="horizontal"
android:padding="12dp">
<!-- User Profile Image -->
<ImageView
android:id="@+id/imgUser"
android:layout_width="50dp"
android:layout_height="50dp"
android:scaleType="centerCrop"
android:src="@drawable/placeholder_image"
android:background="@drawable/placeholder_image" />
<!-- Review Content -->
<LinearLayout
android:layout_width="0dp"

View File

@ -12,7 +12,7 @@
android:hint="@string/fragment_home_search"
android:textColor="@color/soft_gray"
android:textSize="16sp"
android:layout_marginStart="16dp"
android:layout_marginStart="8dp"
android:drawablePadding="8dp"
android:paddingHorizontal="25dp"
android:imeOptions="actionSearch"
@ -37,7 +37,7 @@
android:id="@+id/btn_cart"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="16dp"
android:layout_marginEnd="8dp"
android:padding="8dp"
android:backgroundTint="@color/white"
android:src="@drawable/outline_shopping_cart_24"

View File

@ -47,4 +47,19 @@
<string name="forget_password">Lupa Kata Sandi?</string>
<string name="enter_otp">Masukkan Kode OTP</string>
<string name="sold_product_text">Produk Terlaris</string>
<string name="item_sold">Terjual 10 buah</string>
<string name="product_image">produc image</string>
<string name="ulasan_pembeli">Ulasan Pembeli</string>
<string name="lihat_semua">Lihat Semua</string>
<string name="detail_produk">Detail Produk</string>
<string name="berat_produk">Berat</string>
<string name="stock_product">Stok</string>
<string name="deskripsi_produk">Deskripsi Produk</string>
<string name="kategori">Kategori</string>
<string name="seller_image">Seller Profile Picture</string>
<string name="produk_lainnya">Produk Lainnya</string>
<string name="add_to_cart">Keranjang</string>
<string name="beli_sekarang">Beli Sekarang</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
</resources>

View File

@ -1,6 +1,6 @@
<resources>
<!-- Base application theme. -->
<style name="Theme.Ecommerce_serang" parent="Theme.AppCompat.Light.NoActionBar">
<style name="Theme.Ecommerce_serang" parent="Theme.Material3.Light.NoActionBar">
<!-- Customize your light theme here. -->
<item name="colorPrimary">@color/blue_500</item>
<item name="colorPrimaryDark">@color/white</item>