mirror of
https://github.com/shaulascr/ecommerce_serang.git
synced 2025-08-13 10:42:21 +00:00
2
.idea/gradle.xml
generated
2
.idea/gradle.xml
generated
@ -6,7 +6,7 @@
|
|||||||
<GradleProjectSettings>
|
<GradleProjectSettings>
|
||||||
<option name="testRunner" value="CHOOSE_PER_TEST" />
|
<option name="testRunner" value="CHOOSE_PER_TEST" />
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
<option name="gradleJvm" value="jbr-21" />
|
<option name="gradleJvm" value="openjdk-24" />
|
||||||
<option name="modules">
|
<option name="modules">
|
||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
|
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@ -4,7 +4,7 @@
|
|||||||
<option name="optimizeImportsOnTheFly" value="true" />
|
<option name="optimizeImportsOnTheFly" value="true" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_X" default="true" project-jdk-name="24" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
android:name=".ui.profile.mystore.balance.BalanceTopUpActivity"
|
android:name=".ui.profile.mystore.balance.BalanceTopUpActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.profile.mystore.product.AddProductActivity"
|
android:name=".ui.profile.mystore.product.StoreProductDetailActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.profile.mystore.profile.DetailStoreProfileActivity"
|
android:name=".ui.profile.mystore.profile.DetailStoreProfileActivity"
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
package com.alya.ecommerce_serang.data.api.dto
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
data class Product(
|
||||||
|
|
||||||
|
@field:SerializedName("store_id")
|
||||||
|
val storeId: Int? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("image")
|
||||||
|
val image: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("sppirt")
|
||||||
|
val sppirt: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("rating")
|
||||||
|
val rating: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("description")
|
||||||
|
val description: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("weight")
|
||||||
|
val weight: Int? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("is_pre_order")
|
||||||
|
val isPreOrder: Boolean? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("category_id")
|
||||||
|
val categoryId: Int? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("price")
|
||||||
|
val price: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("name")
|
||||||
|
val name: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("halal")
|
||||||
|
val halal: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("id")
|
||||||
|
val id: Int? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("min_order")
|
||||||
|
val minOrder: Int? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("total_sold")
|
||||||
|
val totalSold: Int? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("stock")
|
||||||
|
val stock: Int? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("status")
|
||||||
|
val status: String? = null
|
||||||
|
)
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.alya.ecommerce_serang.data.api.response
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
data class CreateProductResponse(
|
||||||
|
|
||||||
|
@field:SerializedName("product")
|
||||||
|
val product: Product? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("message")
|
||||||
|
val message: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("preorder")
|
||||||
|
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
|
||||||
|
)
|
@ -17,6 +17,8 @@ import com.alya.ecommerce_serang.data.api.response.ViewStoreProductsResponse
|
|||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
|
import retrofit2.http.Field
|
||||||
|
import retrofit2.http.FormUrlEncoded
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.POST
|
import retrofit2.http.POST
|
||||||
import retrofit2.http.Path
|
import retrofit2.http.Path
|
||||||
@ -69,4 +71,22 @@ interface ApiService {
|
|||||||
@GET("mystore/product") // Replace with actual endpoint
|
@GET("mystore/product") // Replace with actual endpoint
|
||||||
suspend fun getStoreProduct(): Response<ViewStoreProductsResponse>
|
suspend fun getStoreProduct(): Response<ViewStoreProductsResponse>
|
||||||
|
|
||||||
|
@GET("category")
|
||||||
|
fun getCategories(): Call<CategoryResponse>
|
||||||
|
|
||||||
|
@POST("store/createproduct")
|
||||||
|
@FormUrlEncoded
|
||||||
|
suspend fun addProduct(
|
||||||
|
@Field("name") name: String,
|
||||||
|
@Field("description") description: String,
|
||||||
|
@Field("price") price: Int,
|
||||||
|
@Field("stock") stock: Int,
|
||||||
|
@Field("min_order") minOrder: Int,
|
||||||
|
@Field("weight") weight: Int,
|
||||||
|
@Field("is_pre_order") isPreOrder: Boolean,
|
||||||
|
@Field("duration") duration: Int,
|
||||||
|
@Field("category_id") categoryId: Int,
|
||||||
|
@Field("is_active") isActive: String
|
||||||
|
): Response<Unit>
|
||||||
|
|
||||||
}
|
}
|
@ -89,6 +89,44 @@ class ProductRepository(private val apiService: ApiService) {
|
|||||||
throw Exception("Failed to fetch store products: ${response.message()}")
|
throw Exception("Failed to fetch store products: ${response.message()}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun addProduct(
|
||||||
|
name: String,
|
||||||
|
description: String,
|
||||||
|
price: Int,
|
||||||
|
stock: Int,
|
||||||
|
minOrder: Int,
|
||||||
|
weight: Int,
|
||||||
|
isPreOrder: Boolean,
|
||||||
|
duration: Int,
|
||||||
|
categoryId: Int,
|
||||||
|
isActive: Boolean
|
||||||
|
): Result<Unit> = withContext(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
val status = if (isActive) "active" else "inactive"
|
||||||
|
val response = apiService.addProduct(
|
||||||
|
name = name,
|
||||||
|
description = description,
|
||||||
|
price = price,
|
||||||
|
stock = stock,
|
||||||
|
minOrder = minOrder,
|
||||||
|
weight = weight,
|
||||||
|
isPreOrder = isPreOrder,
|
||||||
|
duration = duration,
|
||||||
|
categoryId = categoryId,
|
||||||
|
isActive = status
|
||||||
|
)
|
||||||
|
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
Result.Success(Unit)
|
||||||
|
} else {
|
||||||
|
Result.Error(Exception("Failed to add product. Code: ${response.code()}"))
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Result.Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// suspend fun fetchStoreDetail(storeId: Int): Store? {
|
// suspend fun fetchStoreDetail(storeId: Int): Store? {
|
||||||
|
@ -13,6 +13,7 @@ import com.alya.ecommerce_serang.databinding.ActivityLoginBinding
|
|||||||
import com.alya.ecommerce_serang.ui.MainActivity
|
import com.alya.ecommerce_serang.ui.MainActivity
|
||||||
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.alya.ecommerce_serang.utils.viewmodel.LoginViewModel
|
||||||
|
|
||||||
class LoginActivity : AppCompatActivity() {
|
class LoginActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ import com.alya.ecommerce_serang.databinding.ActivityRegisterBinding
|
|||||||
import com.alya.ecommerce_serang.ui.MainActivity
|
import com.alya.ecommerce_serang.ui.MainActivity
|
||||||
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.alya.ecommerce_serang.utils.viewmodel.RegisterViewModel
|
||||||
|
|
||||||
class RegisterActivity : AppCompatActivity() {
|
class RegisterActivity : AppCompatActivity() {
|
||||||
private lateinit var binding: ActivityRegisterBinding
|
private lateinit var binding: ActivityRegisterBinding
|
||||||
|
@ -7,6 +7,7 @@ import android.view.ViewGroup
|
|||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import com.alya.ecommerce_serang.R
|
import com.alya.ecommerce_serang.R
|
||||||
|
import com.alya.ecommerce_serang.utils.viewmodel.ChatViewModel
|
||||||
|
|
||||||
class ChatFragment : Fragment() {
|
class ChatFragment : Fragment() {
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@ import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
|||||||
import com.alya.ecommerce_serang.utils.HorizontalMarginItemDecoration
|
import com.alya.ecommerce_serang.utils.HorizontalMarginItemDecoration
|
||||||
import com.alya.ecommerce_serang.utils.SessionManager
|
import com.alya.ecommerce_serang.utils.SessionManager
|
||||||
import com.alya.ecommerce_serang.utils.setLightStatusBar
|
import com.alya.ecommerce_serang.utils.setLightStatusBar
|
||||||
|
import com.alya.ecommerce_serang.utils.viewmodel.HomeUiState
|
||||||
|
import com.alya.ecommerce_serang.utils.viewmodel.HomeViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
//@AndroidEntryPoint
|
//@AndroidEntryPoint
|
||||||
|
@ -18,6 +18,7 @@ import com.alya.ecommerce_serang.databinding.ActivityDetailProductBinding
|
|||||||
import com.alya.ecommerce_serang.ui.home.HorizontalProductAdapter
|
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.alya.ecommerce_serang.utils.viewmodel.ProductViewModel
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
|
|
||||||
class DetailProductActivity : AppCompatActivity() {
|
class DetailProductActivity : AppCompatActivity() {
|
||||||
|
@ -13,6 +13,7 @@ import com.alya.ecommerce_serang.data.repository.ProductRepository
|
|||||||
import com.alya.ecommerce_serang.databinding.ActivityReviewProductBinding
|
import com.alya.ecommerce_serang.databinding.ActivityReviewProductBinding
|
||||||
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.alya.ecommerce_serang.utils.viewmodel.ProductViewModel
|
||||||
|
|
||||||
class ReviewProductActivity : AppCompatActivity() {
|
class ReviewProductActivity : AppCompatActivity() {
|
||||||
private lateinit var binding: ActivityReviewProductBinding
|
private lateinit var binding: ActivityReviewProductBinding
|
||||||
|
@ -12,6 +12,7 @@ import com.alya.ecommerce_serang.data.repository.UserRepository
|
|||||||
import com.alya.ecommerce_serang.databinding.ActivityDetailProfileBinding
|
import com.alya.ecommerce_serang.databinding.ActivityDetailProfileBinding
|
||||||
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.alya.ecommerce_serang.utils.viewmodel.ProfileViewModel
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
@ -18,6 +18,7 @@ import com.alya.ecommerce_serang.databinding.FragmentProfileBinding
|
|||||||
import com.alya.ecommerce_serang.ui.profile.mystore.MyStoreActivity
|
import com.alya.ecommerce_serang.ui.profile.mystore.MyStoreActivity
|
||||||
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.alya.ecommerce_serang.utils.viewmodel.ProfileViewModel
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
|
|
||||||
class ProfileFragment : Fragment() {
|
class ProfileFragment : Fragment() {
|
||||||
|
@ -22,6 +22,7 @@ import com.alya.ecommerce_serang.ui.profile.mystore.sells.payment.PaymentFragmen
|
|||||||
import com.alya.ecommerce_serang.ui.profile.mystore.sells.shipment.ShipmentFragment
|
import com.alya.ecommerce_serang.ui.profile.mystore.sells.shipment.ShipmentFragment
|
||||||
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.alya.ecommerce_serang.utils.viewmodel.MyStoreViewModel
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import kotlin.getValue
|
import kotlin.getValue
|
||||||
|
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
package com.alya.ecommerce_serang.ui.profile.mystore.product
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.activity.enableEdgeToEdge
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import androidx.core.view.ViewCompat
|
|
||||||
import androidx.core.view.WindowInsetsCompat
|
|
||||||
import com.alya.ecommerce_serang.R
|
|
||||||
|
|
||||||
class AddProductActivity : AppCompatActivity() {
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
enableEdgeToEdge()
|
|
||||||
setContentView(R.layout.activity_add_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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -11,7 +11,7 @@ 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
|
||||||
import com.alya.ecommerce_serang.databinding.ActivityProductBinding
|
import com.alya.ecommerce_serang.databinding.ActivityProductBinding
|
||||||
import com.alya.ecommerce_serang.ui.product.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
|
||||||
|
|
||||||
@ -74,12 +74,10 @@ class ProductActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.header.headerRightText.setOnClickListener {
|
binding.header.headerRightText.setOnClickListener {
|
||||||
startActivity(Intent(this, AddProductActivity::class.java))
|
startActivity(Intent(this, StoreProductDetailActivity::class.java))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private fun setupRecyclerView() {
|
private fun setupRecyclerView() {
|
||||||
binding.rvStoreProduct.layoutManager = LinearLayoutManager(this)
|
binding.rvStoreProduct.layoutManager = LinearLayoutManager(this)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,175 @@
|
|||||||
|
package com.alya.ecommerce_serang.ui.profile.mystore.product
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.text.Editable
|
||||||
|
import android.text.TextWatcher
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.ArrayAdapter
|
||||||
|
import android.widget.Toast
|
||||||
|
import com.alya.ecommerce_serang.R
|
||||||
|
import androidx.activity.viewModels
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import com.alya.ecommerce_serang.data.api.dto.CategoryItem
|
||||||
|
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
|
||||||
|
import com.alya.ecommerce_serang.data.repository.ProductRepository
|
||||||
|
import com.alya.ecommerce_serang.data.repository.Result
|
||||||
|
import com.alya.ecommerce_serang.databinding.ActivityStoreProductDetailBinding
|
||||||
|
import com.alya.ecommerce_serang.utils.viewmodel.ProductViewModel
|
||||||
|
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
||||||
|
import com.alya.ecommerce_serang.utils.SessionManager
|
||||||
|
import kotlin.getValue
|
||||||
|
|
||||||
|
class StoreProductDetailActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
private lateinit var binding: ActivityStoreProductDetailBinding
|
||||||
|
private lateinit var sessionManager: SessionManager
|
||||||
|
private lateinit var categoryList: List<CategoryItem>
|
||||||
|
|
||||||
|
private val viewModel: ProductViewModel by viewModels {
|
||||||
|
BaseViewModelFactory {
|
||||||
|
sessionManager = SessionManager(this)
|
||||||
|
val apiService = ApiConfig.getApiService(sessionManager)
|
||||||
|
val productRepository = ProductRepository(apiService)
|
||||||
|
ProductViewModel(productRepository)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
binding = ActivityStoreProductDetailBinding.inflate(layoutInflater)
|
||||||
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
setupHeader()
|
||||||
|
observeCategories()
|
||||||
|
viewModel.loadCategories()
|
||||||
|
|
||||||
|
// Setup Pre-Order visibility
|
||||||
|
binding.switchIsPreOrder.setOnCheckedChangeListener { _, isChecked ->
|
||||||
|
binding.layoutDurasi.visibility = if (isChecked) View.VISIBLE else View.GONE
|
||||||
|
validateForm()
|
||||||
|
}
|
||||||
|
|
||||||
|
setupFormValidation()
|
||||||
|
validateForm()
|
||||||
|
|
||||||
|
binding.btnSaveProduct.setOnClickListener {
|
||||||
|
if (binding.btnSaveProduct.isEnabled) addProduct()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupHeader() {
|
||||||
|
binding.header.headerTitle.text = "Tambah Produk"
|
||||||
|
|
||||||
|
binding.header.headerLeftIcon.setOnClickListener {
|
||||||
|
onBackPressedDispatcher.onBackPressed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun observeCategories() {
|
||||||
|
viewModel.categoryList.observe(this) { result ->
|
||||||
|
when (result) {
|
||||||
|
is Result.Loading -> {
|
||||||
|
// Optionally show loading spinner
|
||||||
|
}
|
||||||
|
is Result.Success -> {
|
||||||
|
categoryList = result.data
|
||||||
|
setupCategorySpinner(categoryList)
|
||||||
|
}
|
||||||
|
is Result.Error -> {
|
||||||
|
Toast.makeText(
|
||||||
|
this,
|
||||||
|
"Failed to load categories: ${result.exception.message}",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupCategorySpinner(categories: List<CategoryItem>) {
|
||||||
|
val categoryNames = categories.map { it.name }
|
||||||
|
val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, categoryNames)
|
||||||
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
|
|
||||||
|
binding.spinnerKategoriProduk.adapter = adapter
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addProduct() {
|
||||||
|
val name = binding.edtNamaProduk.text.toString()
|
||||||
|
val description = binding.edtDeskripsiProduk.text.toString()
|
||||||
|
val price = binding.edtHargaProduk.text.toString().toIntOrNull() ?: 0
|
||||||
|
val stock = binding.edtStokProduk.text.toString().toIntOrNull() ?: 0
|
||||||
|
val minOrder = binding.edtMinOrder.text.toString().toIntOrNull() ?: 1
|
||||||
|
val weight = binding.edtBeratProduk.text.toString().toIntOrNull() ?: 0
|
||||||
|
val isPreOrder = binding.switchIsPreOrder.isChecked
|
||||||
|
val duration = binding.edtDurasi.text.toString().toIntOrNull() ?: 0
|
||||||
|
val isActive = binding.switchIsActive.isChecked
|
||||||
|
val categoryPosition = binding.spinnerKategoriProduk.selectedItemPosition
|
||||||
|
val categoryId = categoryList.getOrNull(categoryPosition)?.id ?: 0
|
||||||
|
|
||||||
|
if (isPreOrder && duration == 0) {
|
||||||
|
Toast.makeText(this, "Durasi wajib diisi jika pre-order diaktifkan.", Toast.LENGTH_SHORT).show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.addProduct(
|
||||||
|
name, description, price, stock, minOrder, weight, isPreOrder, duration, categoryId, isActive
|
||||||
|
).observe(this) { result ->
|
||||||
|
when (result) {
|
||||||
|
is Result.Loading -> binding.btnSaveProduct.isEnabled = false
|
||||||
|
is Result.Success -> {
|
||||||
|
Toast.makeText(this, "Produk berhasil ditambahkan!", Toast.LENGTH_SHORT).show()
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
is Result.Error -> {
|
||||||
|
binding.btnSaveProduct.isEnabled = true
|
||||||
|
Toast.makeText(this, "Gagal: ${result.exception.message}", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupFormValidation() {
|
||||||
|
val watcher = object : TextWatcher {
|
||||||
|
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||||
|
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
||||||
|
override fun afterTextChanged(s: Editable?) {
|
||||||
|
validateForm()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Watch all fields
|
||||||
|
binding.edtNamaProduk.addTextChangedListener(watcher)
|
||||||
|
binding.edtDeskripsiProduk.addTextChangedListener(watcher)
|
||||||
|
binding.edtHargaProduk.addTextChangedListener(watcher)
|
||||||
|
binding.edtStokProduk.addTextChangedListener(watcher)
|
||||||
|
binding.edtMinOrder.addTextChangedListener(watcher)
|
||||||
|
binding.edtBeratProduk.addTextChangedListener(watcher)
|
||||||
|
binding.edtDurasi.addTextChangedListener(watcher)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun validateForm() {
|
||||||
|
val isNameValid = binding.edtNamaProduk.text.toString().isNotBlank()
|
||||||
|
val isDescriptionValid = binding.edtDeskripsiProduk.text.toString().isNotBlank()
|
||||||
|
val isPriceValid = binding.edtHargaProduk.text.toString().isNotBlank()
|
||||||
|
val isStockValid = binding.edtStokProduk.text.toString().isNotBlank()
|
||||||
|
val isMinOrderValid = binding.edtMinOrder.text.toString().isNotBlank()
|
||||||
|
val isWeightValid = binding.edtBeratProduk.text.toString().isNotBlank()
|
||||||
|
val isPreOrderChecked = binding.switchIsPreOrder.isChecked
|
||||||
|
val isDurationValid = !isPreOrderChecked || binding.edtDurasi.text.toString().isNotBlank()
|
||||||
|
|
||||||
|
val isFormValid = isNameValid && isDescriptionValid && isPriceValid &&
|
||||||
|
isStockValid && isMinOrderValid && isWeightValid && isDurationValid
|
||||||
|
|
||||||
|
if (isFormValid) {
|
||||||
|
binding.btnSaveProduct.isEnabled = true
|
||||||
|
binding.btnSaveProduct.setBackgroundResource(R.drawable.bg_button_active)
|
||||||
|
binding.btnSaveProduct.setTextColor(ContextCompat.getColor(this, R.color.white))
|
||||||
|
} else {
|
||||||
|
binding.btnSaveProduct.isEnabled = false
|
||||||
|
binding.btnSaveProduct.setBackgroundResource(R.drawable.bg_button_disabled)
|
||||||
|
binding.btnSaveProduct.setTextColor(ContextCompat.getColor(this, R.color.black_300))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,7 @@ 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.MyStoreRepository
|
import com.alya.ecommerce_serang.data.repository.MyStoreRepository
|
||||||
import com.alya.ecommerce_serang.databinding.ActivityDetailStoreProfileBinding
|
import com.alya.ecommerce_serang.databinding.ActivityDetailStoreProfileBinding
|
||||||
import com.alya.ecommerce_serang.ui.profile.mystore.MyStoreViewModel
|
import com.alya.ecommerce_serang.utils.viewmodel.MyStoreViewModel
|
||||||
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
|
||||||
|
@ -7,6 +7,7 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import com.alya.ecommerce_serang.R
|
import com.alya.ecommerce_serang.R
|
||||||
|
import com.alya.ecommerce_serang.utils.viewmodel.ReviewViewModel
|
||||||
|
|
||||||
class ReviewFragment : Fragment() {
|
class ReviewFragment : Fragment() {
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import androidx.viewpager2.widget.ViewPager2
|
|||||||
|
|
||||||
import com.google.android.material.tabs.TabLayoutMediator
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
import com.alya.ecommerce_serang.R
|
import com.alya.ecommerce_serang.R
|
||||||
|
import com.alya.ecommerce_serang.utils.viewmodel.SellsViewModel
|
||||||
|
|
||||||
class SellsFragment : Fragment() {
|
class SellsFragment : Fragment() {
|
||||||
private lateinit var viewModel: SellsViewModel
|
private lateinit var viewModel: SellsViewModel
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.alya.ecommerce_serang.ui.chat
|
package com.alya.ecommerce_serang.utils.viewmodel
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.alya.ecommerce_serang.ui.home
|
package com.alya.ecommerce_serang.utils.viewmodel
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
@ -1,4 +1,4 @@
|
|||||||
package com.alya.ecommerce_serang.ui.auth
|
package com.alya.ecommerce_serang.utils.viewmodel
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
@ -10,12 +10,12 @@ import com.alya.ecommerce_serang.data.repository.UserRepository
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class LoginViewModel(private val repository: UserRepository) : ViewModel() {
|
class LoginViewModel(private val repository: UserRepository) : ViewModel() {
|
||||||
private val _loginState = MutableLiveData<com.alya.ecommerce_serang.data.repository.Result<LoginResponse>>()
|
private val _loginState = MutableLiveData<Result<LoginResponse>>()
|
||||||
val loginState: LiveData<Result<LoginResponse>> get() = _loginState
|
val loginState: LiveData<Result<LoginResponse>> get() = _loginState
|
||||||
|
|
||||||
fun login(email: String, password: String) {
|
fun login(email: String, password: String) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
_loginState.value = com.alya.ecommerce_serang.data.repository.Result.Loading
|
_loginState.value = Result.Loading
|
||||||
val result = repository.login(email, password)
|
val result = repository.login(email, password)
|
||||||
_loginState.value = result
|
_loginState.value = result
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.alya.ecommerce_serang.ui.profile.mystore
|
package com.alya.ecommerce_serang.utils.viewmodel
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
@ -1,9 +1,11 @@
|
|||||||
package com.alya.ecommerce_serang.ui.product
|
package com.alya.ecommerce_serang.utils.viewmodel
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.liveData
|
||||||
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.ProductsItem
|
import com.alya.ecommerce_serang.data.api.dto.ProductsItem
|
||||||
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
|
import com.alya.ecommerce_serang.data.api.response.Product
|
||||||
@ -23,10 +25,12 @@ class ProductViewModel(private val repository: ProductRepository) : ViewModel()
|
|||||||
private val _reviewProduct = MutableLiveData<List<ReviewsItem>>()
|
private val _reviewProduct = MutableLiveData<List<ReviewsItem>>()
|
||||||
val reviewProduct: LiveData<List<ReviewsItem>> get() = _reviewProduct
|
val reviewProduct: LiveData<List<ReviewsItem>> get() = _reviewProduct
|
||||||
|
|
||||||
// For List of Products in My Store
|
|
||||||
private val _productList = MutableLiveData<Result<List<ProductsItem>>>()
|
private val _productList = MutableLiveData<Result<List<ProductsItem>>>()
|
||||||
val productList: LiveData<Result<List<ProductsItem>>> get() = _productList
|
val productList: LiveData<Result<List<ProductsItem>>> get() = _productList
|
||||||
|
|
||||||
|
private val _categoryList = MutableLiveData<Result<List<CategoryItem>>>()
|
||||||
|
val categoryList: LiveData<Result<List<CategoryItem>>> get() = _categoryList
|
||||||
|
|
||||||
fun loadProductDetail(productId: Int) {
|
fun loadProductDetail(productId: Int) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val result = repository.fetchProductDetail(productId)
|
val result = repository.fetchProductDetail(productId)
|
||||||
@ -53,6 +57,34 @@ class ProductViewModel(private val repository: ProductRepository) : ViewModel()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun loadCategories() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
_categoryList.value = Result.Loading
|
||||||
|
_categoryList.value = repository.getAllCategories()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addProduct(
|
||||||
|
name: String,
|
||||||
|
description: String,
|
||||||
|
price: Int,
|
||||||
|
stock: Int,
|
||||||
|
minOrder: Int,
|
||||||
|
weight: Int,
|
||||||
|
isPreOrder: Boolean,
|
||||||
|
duration: Int,
|
||||||
|
categoryId: Int,
|
||||||
|
isActive: Boolean
|
||||||
|
): LiveData<Result<Unit>> = liveData {
|
||||||
|
emit(Result.Loading)
|
||||||
|
val result = repository.addProduct(
|
||||||
|
name, description, price, stock, minOrder, weight, isPreOrder, duration, categoryId, isActive
|
||||||
|
)
|
||||||
|
emit(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 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 {
|
@ -1,4 +1,4 @@
|
|||||||
package com.alya.ecommerce_serang.ui.profile
|
package com.alya.ecommerce_serang.utils.viewmodel
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
@ -1,4 +1,4 @@
|
|||||||
package com.alya.ecommerce_serang.ui.auth
|
package com.alya.ecommerce_serang.utils.viewmodel
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
@ -87,7 +87,3 @@ class RegisterViewModel(private val repository: UserRepository) : ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.alya.ecommerce_serang.ui.profile.mystore.review
|
package com.alya.ecommerce_serang.utils.viewmodel
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.alya.ecommerce_serang.ui.profile.mystore.sells
|
package com.alya.ecommerce_serang.utils.viewmodel
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
|
@ -7,7 +7,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:context=".ui.profile.mystore.product.AddProductActivity">
|
tools:context=".ui.profile.mystore.product.StoreProductDetailActivity">
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/header"
|
android:id="@+id/header"
|
||||||
@ -214,7 +214,7 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/DeskripsiProduk"
|
android:id="@+id/edt_deskripsi_produk"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="70dp"
|
android:layout_height="70dp"
|
||||||
android:background="@drawable/bg_text_field"
|
android:background="@drawable/bg_text_field"
|
||||||
@ -434,14 +434,109 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- Kondisi Produk -->
|
<!-- <!– Kondisi Produk –>-->
|
||||||
|
<!-- <LinearLayout-->
|
||||||
|
<!-- android:layout_width="match_parent"-->
|
||||||
|
<!-- android:layout_height="wrap_content"-->
|
||||||
|
<!-- android:orientation="vertical"-->
|
||||||
|
<!-- android:layout_marginBottom="24dp">-->
|
||||||
|
|
||||||
|
<!-- <!– Label Kondisi Produk –>-->
|
||||||
|
<!-- <LinearLayout-->
|
||||||
|
<!-- android:layout_width="match_parent"-->
|
||||||
|
<!-- android:layout_height="wrap_content"-->
|
||||||
|
<!-- android:orientation="horizontal">-->
|
||||||
|
|
||||||
|
<!-- <TextView-->
|
||||||
|
<!-- android:layout_width="wrap_content"-->
|
||||||
|
<!-- android:layout_height="wrap_content"-->
|
||||||
|
<!-- android:text="Kondisi Produk"-->
|
||||||
|
<!-- style="@style/body_medium"-->
|
||||||
|
<!-- android:layout_marginEnd="4dp"/>-->
|
||||||
|
|
||||||
|
<!-- <TextView-->
|
||||||
|
<!-- android:layout_width="0dp"-->
|
||||||
|
<!-- android:layout_height="wrap_content"-->
|
||||||
|
<!-- android:layout_weight="1"-->
|
||||||
|
<!-- android:text="*"-->
|
||||||
|
<!-- style="@style/body_medium"-->
|
||||||
|
<!-- android:textColor="@color/red_required"-->
|
||||||
|
<!-- android:layout_gravity="end"/>-->
|
||||||
|
|
||||||
|
<!-- </LinearLayout>-->
|
||||||
|
|
||||||
|
<!-- <!– Spinner Dropdown dengan Chevron –>-->
|
||||||
|
<!-- <LinearLayout-->
|
||||||
|
<!-- android:layout_width="match_parent"-->
|
||||||
|
<!-- android:layout_height="wrap_content"-->
|
||||||
|
<!-- android:orientation="horizontal"-->
|
||||||
|
<!-- android:background="@drawable/bg_text_field"-->
|
||||||
|
<!-- android:gravity="center_vertical"-->
|
||||||
|
<!-- android:layout_marginTop="10dp">-->
|
||||||
|
|
||||||
|
<!-- <Spinner-->
|
||||||
|
<!-- android:id="@+id/spinner_kondisi_produk"-->
|
||||||
|
<!-- android:layout_width="0dp"-->
|
||||||
|
<!-- android:layout_height="wrap_content"-->
|
||||||
|
<!-- android:layout_weight="1"-->
|
||||||
|
<!-- android:padding="8dp"-->
|
||||||
|
<!-- style="@style/body_small"-->
|
||||||
|
<!-- android:background="@null"/>-->
|
||||||
|
|
||||||
|
<!-- <!– Chevron Down Icon –>-->
|
||||||
|
<!-- <ImageView-->
|
||||||
|
<!-- android:layout_width="16dp"-->
|
||||||
|
<!-- android:layout_height="16dp"-->
|
||||||
|
<!-- android:src="@drawable/ic_down"-->
|
||||||
|
<!-- android:layout_marginEnd="8dp"-->
|
||||||
|
<!-- android:contentDescription="Chevron Down" />-->
|
||||||
|
|
||||||
|
<!-- </LinearLayout>-->
|
||||||
|
|
||||||
|
<!-- </LinearLayout>-->
|
||||||
|
|
||||||
|
<!-- Pre-Order -->
|
||||||
<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">
|
||||||
|
|
||||||
<!-- Label Kondisi Produk -->
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="Pre-Order"
|
||||||
|
style="@style/body_medium"
|
||||||
|
android:layout_marginEnd="4dp"/>
|
||||||
|
|
||||||
|
<Switch
|
||||||
|
android:id="@+id/switch_is_pre_order"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
tools:ignore="UseSwitchCompatOrMaterialXml" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Durasi Pre-Order -->
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_durasi"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_marginBottom="24dp"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<!-- Label Durasi Pre-Order -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -450,10 +545,11 @@
|
|||||||
<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="Durasi Pre-Order"
|
||||||
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"
|
||||||
@ -465,31 +561,32 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- Spinner Dropdown dengan Chevron -->
|
<!-- Input Durasi Pre-Order dengan Suffix "hari" -->
|
||||||
<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">
|
||||||
android:layout_marginTop="10dp">
|
|
||||||
|
|
||||||
<Spinner
|
<EditText
|
||||||
android:id="@+id/spinner_kondisi_produk"
|
android:id="@+id/edt_durasi"
|
||||||
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:hint="Isi durasi pre-order di sini"
|
||||||
|
android:inputType="number"
|
||||||
style="@style/body_small"
|
style="@style/body_small"
|
||||||
android:background="@null"/>
|
android:background="@null"
|
||||||
|
android:padding="8dp"/>
|
||||||
|
|
||||||
<!-- Chevron Down Icon -->
|
<TextView
|
||||||
<ImageView
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="16dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="16dp"
|
android:text="hari"
|
||||||
android:src="@drawable/ic_down"
|
style="@style/label_medium_prominent"
|
||||||
android:layout_marginEnd="8dp"
|
android:textColor="@color/black_300"
|
||||||
android:contentDescription="Chevron Down" />
|
android:padding="8dp"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -530,7 +627,8 @@
|
|||||||
<Button
|
<Button
|
||||||
android:id="@+id/btn_save_product"
|
android:id="@+id/btn_save_product"
|
||||||
android:text="Simpan Produk"
|
android:text="Simpan Produk"
|
||||||
style="@style/button.large.disabled.long"/>
|
style="@style/button.large.disabled.long"
|
||||||
|
android:enabled="false"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
Reference in New Issue
Block a user