Bläddra i källkod

admin page in progress

dola 1 år sedan
förälder
incheckning
adce803ddd

+ 5 - 1
app/src/main/java/com/sambath/kunkhmer/adapter/ProductAdapter.kt

@@ -24,7 +24,11 @@ class ProductAdapter(var cardList: MutableList<ProductInfo>, private val listene
     override fun onBindViewHolder(holder: ProductAdapter.ViewHolder, position: Int) {
         val currentItem = cardList[position]
 
-        Picasso.get().load(Config.BASE_URL + "/v1/product/image/" + currentItem.filename).into(holder.imageView)
+        if(currentItem.filename == null) {
+            Picasso.get().load(R.drawable.default_background).into(holder.imageView)
+        } else {
+            Picasso.get().load(Config.BASE_URL + "/v1/product/image/" + currentItem.filename).into(holder.imageView)
+        }
         holder.subTitleTextView.text = currentItem.desc
         holder.titleTextView.text = currentItem.name
         holder.priceTextView.text = "$" + currentItem.price

+ 49 - 1
app/src/main/java/com/sambath/kunkhmer/remote/ProductDataModel.kt

@@ -32,5 +32,53 @@ data class ProductInfo(
     @Json(name = "createdAt")
     val createdAt: String,
     @Json(name = "filename")
-    val filename: String,
+    val filename: String? = null,
+)
+
+///////
+
+@JsonClass(generateAdapter = true)
+class CreateProductRequest(
+    @Json(name = "name")
+    val name: String,
+    @Json(name = "desc")
+    val desc: String,
+    @Json(name = "price")
+    val price: String,
+    @Json(name = "upload")
+    val upload: String
+)
+
+@JsonClass(generateAdapter = true)
+data class CreateProductResponse(
+    @Json(name = "code")
+    val resultCode: Int,
+    @Json(name = "message")
+    val message: ResponseMessage,
+    @Json(name = "data")
+    val data: ProductCreatedData?
+)
+
+@JsonClass(generateAdapter = true)
+data class ProductCreatedData(
+    @Json(name = "product")
+    val obj: CreatedProduct,
+)
+
+@JsonClass(generateAdapter = true)
+data class CreatedProduct(
+    @Json(name = "_id")
+    val id: String,
+    @Json(name = "price")
+    val price: Int,
+    @Json(name = "name")
+    val name: String,
+    @Json(name = "desc")
+    val desc: String,
+    @Json(name = "createdAt")
+    val createdAt: String,
+    @Json(name = "updatedAt")
+    val updatedAt: String,
+    @Json(name = "__v")
+    val _v: Int,
 )

+ 3 - 0
app/src/main/java/com/sambath/kunkhmer/remote/service/ApiService.kt

@@ -47,6 +47,9 @@ interface ApiService {
 
     @POST("/v1/event/create")
     fun createEvent(@Body createEventRequest: CreateEventRequest): Single<CreateEventResponse>
+
+    @POST("/v1/product/create")
+    fun createProduct(@Body createProductRequest: CreateProductRequest): Single<CreateProductResponse>
     ///---------------------------------------------------------
 
     @POST("/v1/api/user/changepassword")

+ 77 - 38
app/src/main/java/com/sambath/kunkhmer/screen/shop/ShopAdminFragment.kt

@@ -1,60 +1,99 @@
 package com.sambath.kunkhmer.screen.shop
 
+import android.app.Activity
+import android.content.Intent
+import android.net.Uri
 import android.os.Bundle
 import androidx.fragment.app.Fragment
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import android.widget.Toast
+import androidx.activity.result.ActivityResultLauncher
+import androidx.activity.result.contract.ActivityResultContracts
 import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.app.App
+import com.sambath.kunkhmer.remote.CreateProductRequest
+import kotlinx.android.synthetic.main.fragment_shop_admin.view.et_desc
+import kotlinx.android.synthetic.main.fragment_shop_admin.view.submitButton
+import kotlinx.android.synthetic.main.fragment_shop_admin.view.uploadButton
+import kotlinx.android.synthetic.main.fragment_shop_admin.view.et_name
+import kotlinx.android.synthetic.main.fragment_shop_admin.view.et_price
+import kotlinx.android.synthetic.main.fragment_shop_admin.view.uploadedImageView
 
-// 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 [ShopAdminFragment.newInstance] factory method to
- * create an instance of this fragment.
- */
 class ShopAdminFragment : Fragment() {
-    // TODO: Rename and change types of parameters
-    private var param1: String? = null
-    private var param2: String? = null
+    private var _root: View? = null
+    private val binding get() = _root!!
+    private lateinit var shopViewModel: ShopViewModel
+    private var imageUri: Uri? = 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? {
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+        _root = inflater.inflate(R.layout.fragment_shop_admin, container, false)
+
+        setDefault()
+
+        shopViewModel = ShopViewModel(App.injectApiService(), App.injectPrefHelper())
+        shopViewModel.state.observe(viewLifecycleOwner, androidx.lifecycle.Observer {
+            render(it)
+        })
+        binding.uploadButton.setOnClickListener {
+            openImagePicker()
+        }
+
+        binding.submitButton.setOnClickListener {
+            val createProductRequest = CreateProductRequest(
+                binding.et_name.text.toString(),
+                binding.et_desc.text.toString(),
+                binding.et_price.text.toString(),
+                imageUri.toString()
+            )
+
+            shopViewModel.createProduct(createProductRequest.name, createProductRequest.desc, createProductRequest.price, createProductRequest.upload)
+        }
+
         // Inflate the layout for this fragment
-        return inflater.inflate(R.layout.fragment_shop_admin, container, false)
+        return binding
     }
 
-    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 ShopAdminFragment.
-         */
-        // TODO: Rename and change types and number of parameters
-        @JvmStatic
-        fun newInstance(param1: String, param2: String) =
-            ShopAdminFragment().apply {
-                arguments = Bundle().apply {
-                    putString(ARG_PARAM1, param1)
-                    putString(ARG_PARAM2, param2)
+    private fun setDefault(){
+        binding.et_name.setText("Bubu")
+        binding.et_price.setText("10")
+        binding.et_desc.setText("Bubu and Dudu")
+    }
+
+    private fun render(state: ShopViewModel.ProductViewState) {
+        if (state.isLoginSuccess) {
+            Toast.makeText(context, "Create Success...", Toast.LENGTH_LONG).show()
+
+            binding.et_name.setText("")
+            binding.et_price.setText("")
+            binding.et_desc.setText("")
+            binding.uploadedImageView.setImageDrawable(null)
+        }
+        // Other state handling...
+    }
+
+    private val imagePicker: ActivityResultLauncher<Intent> =
+        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
+            if (result.resultCode == Activity.RESULT_OK) {
+                val data: Intent? = result.data
+                if (data != null) {
+                    imageUri = data.data // The URI of the selected image
+                    if (imageUri != null) {
+                        // Load and display the selected image in the ImageView
+                        binding.uploadedImageView.setImageURI(imageUri)
+                    }
                 }
             }
+        }
+
+    private fun openImagePicker() {
+        val intent = Intent(Intent.ACTION_GET_CONTENT)
+        intent.type = "image/*"
+        imagePicker.launch(intent)
     }
 }

+ 27 - 0
app/src/main/java/com/sambath/kunkhmer/screen/shop/ShopViewModel.kt

@@ -1,9 +1,12 @@
 package com.sambath.kunkhmer.screen.shop
 
+import android.util.Log
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import com.sambath.kunkhmer.app.getErrorCode
 import com.sambath.kunkhmer.base.BaseViewModel
+import com.sambath.kunkhmer.remote.CreateNewsRequest
+import com.sambath.kunkhmer.remote.CreateProductRequest
 import com.sambath.kunkhmer.remote.LivesInfo
 import com.sambath.kunkhmer.remote.ProductInfo
 import com.sambath.kunkhmer.remote.service.ApiService
@@ -47,4 +50,28 @@ class ShopViewModel(val apiService: ApiService, val prefHelper: PrefHelper) : Ba
                 })
         )
     }
+
+    fun createProduct(name: String, desc: String, price: String, upload: String) {
+        if (_state.value!!.isProgress) return
+        val request = CreateProductRequest(name, desc, price, upload)
+        _state.value = prev().copy(isProgress = true)
+
+        disposables.add(
+            apiService.createProduct(request)
+                .timeout(10, TimeUnit.SECONDS)
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe({
+                    Log.d("login", it.toString())
+                    if (it.resultCode == 1) {
+                        _state.value = prev().copy(isProgress = false, isLoginSuccess = true)
+                    } else {
+                        _state.value = prev().copy(isProgress = false, error = "[${it.message.description}]")
+                    }
+                }, {
+                    val message: String = "ប្រតិបត្តិការមិនជោគជ័យ " + it.getErrorCode() + it.message
+                    _state.value = prev().copy(isProgress = false, error = message)
+                })
+        )
+    }
 }

+ 92 - 8
app/src/main/res/layout/fragment_shop_admin.xml

@@ -1,14 +1,98 @@
 <?xml version="1.0" encoding="utf-8"?>
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    tools:context=".screen.shop.ShopAdminFragment">
+    android:background="@color/color_black"
+    android:orientation="vertical"
+    android:padding="10dp">
 
-    <!-- TODO: Update blank fragment layout -->
-    <TextView
+    <com.google.android.material.textfield.TextInputLayout
+        android:id="@+id/til_name"
+        style="@style/BoxInputLayout"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:text="@string/hello_blank_fragment" />
+        android:layout_height="48dp"
+        android:layout_below="@id/tv_username"
+        app:endIconMode="clear_text"
+        app:hintEnabled="false">
 
-</FrameLayout>
+        <androidx.appcompat.widget.AppCompatEditText
+            android:id="@+id/et_name"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:background="@color/color_white"
+            android:hint="@string/hint_product_name"
+            android:inputType="text"
+            android:maxLength="50"
+            android:padding="0dp" />
+    </com.google.android.material.textfield.TextInputLayout>
+
+    <com.google.android.material.textfield.TextInputLayout
+        android:id="@+id/til_price"
+        style="@style/BoxInputLayout"
+        android:layout_width="match_parent"
+        android:layout_height="48dp"
+        android:layout_below="@id/tv_username"
+        app:endIconMode="clear_text"
+        app:hintEnabled="false">
+
+        <androidx.appcompat.widget.AppCompatEditText
+            android:id="@+id/et_price"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:background="@color/color_white"
+            android:hint="@string/hint_price"
+            android:inputType="number"
+            android:maxLength="50"
+            android:padding="0dp" />
+    </com.google.android.material.textfield.TextInputLayout>
+
+    <com.google.android.material.textfield.TextInputLayout
+        android:id="@+id/til_desc"
+        style="@style/BoxInputLayout"
+        android:layout_width="match_parent"
+        android:layout_height="200dp"
+        android:layout_below="@id/tv_username"
+        app:endIconMode="clear_text"
+        app:hintEnabled="false">
+
+        <androidx.appcompat.widget.AppCompatEditText
+            android:id="@+id/et_desc"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:background="@color/color_white"
+            android:gravity="top"
+            android:hint="@string/hint_desc"
+            android:inputType="text"
+            android:maxLength="50"
+            android:padding="0dp" />
+    </com.google.android.material.textfield.TextInputLayout>
+
+    <Button
+        android:id="@+id/uploadButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:layout_marginBottom="16dp"
+        android:paddingStart="16dp"
+        android:paddingEnd="16dp"
+        android:text="Upload Image" />
+
+    <ImageView
+        android:id="@+id/uploadedImageView"
+        android:layout_width="200dp"
+        android:layout_height="200dp"
+        android:layout_gravity="center"
+        android:layout_marginBottom="16dp"
+        android:background="@color/color_gray_300"
+        android:scaleType="centerCrop" />
+
+    <Button
+        android:id="@+id/submitButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:paddingStart="16dp"
+        android:paddingEnd="16dp"
+        android:text="Submit" />
+</LinearLayout>

+ 2 - 0
app/src/main/res/values/strings.xml

@@ -104,4 +104,6 @@
     <string name="hint_fighter_1">Fighter 1</string>
     <string name="hint_fighter_2">Fighter 2</string>
     <string name="hint_match_fighter_id">Match Fighter Id</string>
+    <string name="hint_price">Price</string>
+    <string name="hint_product_name">Product Name</string>
 </resources>