Browse Source

product model

dola 1 year ago
parent
commit
fb16502dbc

+ 66 - 0
app/src/main/java/com/sambath/kunkhmer/adapter/TopNewsDetailAdapter.kt

@@ -0,0 +1,66 @@
+package com.sambath.kunkhmer.adapter
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.config.Config
+import com.sambath.kunkhmer.remote.News
+import com.sambath.kunkhmer.remote.NewsDetail
+import com.squareup.picasso.Picasso
+import java.text.SimpleDateFormat
+import java.util.Locale
+import java.util.TimeZone
+
+class TopNewsDetailAdapter(var newsDetail: NewsDetail) : RecyclerView.Adapter<TopNewsDetailAdapter.ViewHolder>() {
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+        val itemView = LayoutInflater.from(parent.context).inflate(R.layout.layout_news_detail, parent, false)
+        return ViewHolder(itemView)
+    }
+
+    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+        val currentItem = newsDetail
+        if (!currentItem.filename.isNullOrEmpty()) {
+            Picasso.get()
+                .load(Config.BASE_URL + "/v1/new/image/" + currentItem.filename)
+                .into(holder.imageView);
+        } else {
+            Picasso.get()
+                .load(R.drawable.ic_logo_header)
+                .into(holder.imageView);
+        }
+        if (!currentItem.createdAt.isNullOrEmpty())
+            holder.dateTextView.text = parseAndFormatDate(currentItem.createdAt)
+        holder.titleTextView.text = currentItem.title
+        holder.subTextView.text = currentItem.desc
+    }
+
+    override fun getItemCount() = 1
+
+    // Holds the views for adding it to image and text
+    class ViewHolder(ItemView: View) : RecyclerView.ViewHolder(ItemView) {
+        val imageView: ImageView = itemView.findViewById(R.id.imageView)
+        val dateTextView: TextView = itemView.findViewById(R.id.news_date)
+        val titleTextView: TextView = itemView.findViewById(R.id.news_title)
+        val subTextView: TextView = itemView.findViewById(R.id.news_desc)
+    }
+
+    private fun parseAndFormatDate(dateString: String): String {
+        // Create a SimpleDateFormat for parsing the date string
+        val parser = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault())
+        parser.timeZone = TimeZone.getTimeZone("UTC")
+
+        // Parse the date
+        val date = parser.parse(dateString)
+
+        // Create a SimpleDateFormat for formatting the date
+        val formatter = SimpleDateFormat("dd MMM yyyy HH:mm", Locale.getDefault())
+        formatter.timeZone = TimeZone.getDefault() // Use local timezone
+
+        // Format the date
+        return formatter.format(date)
+    }
+}

+ 47 - 0
app/src/main/java/com/sambath/kunkhmer/remote/NewsDetailDataModel.kt

@@ -0,0 +1,47 @@
+package com.sambath.kunkhmer.remote
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+data class NewsDetailResponse(
+    @Json(name = "code")
+    val resultCode: Int,
+    @Json(name = "message")
+    val message: ResponseMessage,
+    @Json(name = "data")
+    val data: NewsDetailData?
+)
+
+@JsonClass(generateAdapter = true)
+data class NewsDetailData(
+    @Json(name = "object")
+    val obj: NewsDetail,
+)
+
+@JsonClass(generateAdapter = true)
+data class NewsDetail(
+    @Json(name = "viewer")
+    val viewer: Int = 0,
+
+    @Json(name = "_id")
+    val id: String = "",
+
+    @Json(name = "title")
+    val title: 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 = 0,
+
+    @Json(name = "filename")
+    val filename: String = ""
+)

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

@@ -31,6 +31,9 @@ interface ApiService {
 
     @GET("/v1/product/getAll")
     fun getProducts(): Single<ProductResponse>
+
+    @GET("/v1/new/get/{newsId}")
+    fun getNewsDetail(@Path("newsId") newsId: String): Single<NewsDetailResponse>
     ///---------------------------------------------------------
 
     @POST("/v1/api/user/changepassword")

+ 50 - 0
app/src/main/java/com/sambath/kunkhmer/screen/news/NewsDetailViewModel.kt

@@ -0,0 +1,50 @@
+package com.sambath.kunkhmer.screen.news
+
+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.NewsDetail
+import com.sambath.kunkhmer.remote.service.ApiService
+import com.sambath.kunkhmer.util.PrefHelper
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.schedulers.Schedulers
+import java.util.concurrent.TimeUnit
+
+
+data class NewsDetailViewState(
+    val initial: Boolean = false,
+    val isProgress: Boolean = false,
+    val isLoginSuccess: Boolean = false,
+    val error: String? = null,
+    val newsDetailData: NewsDetail? = null,
+)
+
+class NewsDetailViewModel(val apiService: ApiService, val prefHelper: PrefHelper) : BaseViewModel()  {
+    private val _state = MutableLiveData(NewsDetailViewState())
+    val state: LiveData<NewsDetailViewState> = _state
+    private fun prev() = _state.value!!
+
+    fun getNewsDetail(id: String){
+        if (_state.value!!.isProgress) return
+        _state.value = prev().copy(isProgress = true)
+
+        disposables.add(
+            apiService.getNewsDetail(id)
+                .timeout(10, TimeUnit.SECONDS)
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe({
+                    if (it.resultCode == 1) {
+                        _state.value = prev().copy(isProgress = false, isLoginSuccess = true, newsDetailData = it.data!!.obj)
+                    } else {
+                        _state.value =
+                            prev().copy(isProgress = false, error = "[${it.message.description}]")
+                    }
+                }, {
+                    val message: String = "ប្រតិបត្តិការមិនជោគជ័យ " + it.getErrorCode()
+                    _state.value = prev().copy(isProgress = false, error = message)
+                })
+        )
+    }
+}

+ 36 - 0
app/src/main/java/com/sambath/kunkhmer/screen/news/TopNewsDetailFragment.kt

@@ -5,13 +5,20 @@ import androidx.fragment.app.Fragment
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import androidx.recyclerview.widget.LinearLayoutManager
 import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.adapter.TopNewsDetailAdapter
+import com.sambath.kunkhmer.app.App
 import com.sambath.kunkhmer.remote.News
+import com.sambath.kunkhmer.remote.NewsDetail
+import kotlinx.android.synthetic.main.fragment_top_news_detail.view.recyclerViewTopNewDetail
 
 class TopNewsDetailFragment : Fragment() {
     private var _root: View? = null
     private val binding get() = _root!!
     private var newsItem: News? = null
+    private lateinit var newsDetailViewModel: NewsDetailViewModel
+    private lateinit var topNewsDetailAdapter: TopNewsDetailAdapter
 
 
     override fun onCreate(savedInstanceState: Bundle?) {
@@ -21,6 +28,35 @@ class TopNewsDetailFragment : Fragment() {
     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
         _root = inflater.inflate(R.layout.fragment_top_news_detail, container, false)
         val newsId = arguments?.getString("news_id")
+
+        topNewsDetailAdapter = TopNewsDetailAdapter(NewsDetail())
+
+        // Set adapters
+        binding.recyclerViewTopNewDetail.apply {
+            layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
+            adapter = topNewsDetailAdapter
+        }
+
+        newsDetailViewModel = NewsDetailViewModel(App.injectApiService(), App.injectPrefHelper())
+        newsDetailViewModel.getNewsDetail(newsId!!)
+        newsDetailViewModel.state.observe(viewLifecycleOwner, androidx.lifecycle.Observer {
+            render(it)
+        })
+
         return _root
     }
+
+    private fun render(state: NewsDetailViewState) {
+        if (state.isLoginSuccess) {
+            if(state.newsDetailData != null) {
+                updateNewsDetailFeed(state.newsDetailData)
+            }
+        }
+        // Other state handling...
+    }
+
+    private fun updateNewsDetailFeed(newsDetailData: NewsDetail) {
+        topNewsDetailAdapter.newsDetail = newsDetailData
+        topNewsDetailAdapter.notifyDataSetChanged()
+    }
 }

+ 10 - 4
app/src/main/res/layout/fragment_top_news_detail.xml

@@ -1,14 +1,20 @@
 <?xml version="1.0" encoding="utf-8"?>
 <FrameLayout 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:layout_width="match_parent"
     android:layout_height="match_parent"
     tools:context=".screen.news.TopNewsDetailFragment">
 
-    <!-- TODO: Update blank fragment layout -->
-    <TextView
+    <androidx.core.widget.NestedScrollView
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:text="@string/hello_blank_fragment" />
+        android:layout_height="wrap_content">
+
+        <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/recyclerViewTopNewDetail"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
+    </androidx.core.widget.NestedScrollView>
 
 </FrameLayout>

+ 54 - 0
app/src/main/res/layout/layout_news_detail.xml

@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/color_black"
+    android:orientation="vertical"
+    android:padding="10dp">
+
+    <TextView
+        android:id="@+id/news_title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="5dp"
+        android:paddingBottom="5dp"
+        android:text="@string/news_detail_title"
+        android:textColor="@color/color_white"
+        android:textSize="20sp"
+        android:textStyle="bold" />
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:background="@color/color_white" />
+
+    <TextView
+        android:id="@+id/news_date"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="5dp"
+        android:paddingBottom="5dp"
+        android:text="@string/date"
+        android:textColor="@color/color_gray_400"
+        android:textSize="14sp" />
+
+    <ImageView
+        android:id="@+id/imageView"
+        android:layout_width="match_parent"
+        android:layout_height="250dp"
+        android:scaleType="fitCenter"
+        android:src="@drawable/ic_logo_header" />
+
+    <TextView
+        android:id="@+id/news_desc"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="5dp"
+        android:paddingBottom="5dp"
+        android:scrollbarSize="8dp"
+        android:scrollbarStyle="outsideOverlay"
+        android:text="@string/description"
+        android:textColor="@color/color_white"
+        android:textSize="14sp" />
+
+</androidx.appcompat.widget.LinearLayoutCompat>

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

@@ -82,4 +82,6 @@
     <string name="booking_now">Booking Now</string>
     <string name="shope_title">HOME BOXING EQUIPMENT</string>
     <string name="shope_title_2">WHAT YOU NEED TO TRAIN AT HOME</string>
+    <string name="news_detail_title">News Title</string>
+    <string name="description">Description</string>
 </resources>