Skip to content

Commit

Permalink
Merge 5431fd5 into b92301e
Browse files Browse the repository at this point in the history
  • Loading branch information
muhammedesadcomert authored Sep 11, 2022
2 parents b92301e + 5431fd5 commit 1657b69
Show file tree
Hide file tree
Showing 17 changed files with 388 additions and 53 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ android {
minSdk 23
targetSdk 32
versionCode 1
versionName "1.0.1"
versionName "1.2.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ abstract class BaseRepository {
} catch (e: HttpException) {
Resource.Failure(e.message ?: "Something went wrong!")
} catch (e: IOException) {
Resource.Failure("Please check your internet connection")
Resource.Failure(e.message ?: "Please check your internet connection")
} catch (e: Exception) {
Resource.Failure("Something went wrong!")
Resource.Failure(e.message ?: "Something went wrong!")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ object Constant {
const val BASE_URL = "https://api.shopiroller.com/v2.0/"
const val API_KEY = "xXspnfUxPzOGKNu90bFAjlOTnMLpN8veiixvEFXUw9I="
const val ALIAS_KEY = "AtS1aPFxlIdVLth6ee2SEETlRxk="
}
const val DEFAULT_CATEGORY = "61b1f109a82ec0dd1c56f5ed" // Economic Menu
const val DEFAULT_SORT = "Price"
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
package com.muhammedesadcomert.shopping.data.remote

import com.muhammedesadcomert.shopping.ui.home.model.CategoryApiModel
import com.muhammedesadcomert.shopping.ui.home.model.ProductApiModel
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Query

interface ApiService {
@GET("categories")
suspend fun getCategories(): Response<CategoryApiModel>
}

@GET("products/advanced-filtered")
suspend fun getProducts(
@Query("categoryId") categoryId: String,
@Query("sort") sort: String,
): Response<ProductApiModel>
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ import com.muhammedesadcomert.shopping.common.base.BaseRepository
import com.muhammedesadcomert.shopping.common.util.Resource
import com.muhammedesadcomert.shopping.data.remote.ApiService
import com.muhammedesadcomert.shopping.ui.home.model.CategoryApiModel
import com.muhammedesadcomert.shopping.ui.home.model.ProductApiModel
import javax.inject.Inject

class ProductRepository @Inject constructor(private val apiService: ApiService) : BaseRepository() {
suspend fun getCategories(): Resource<CategoryApiModel> =
safeApiCall { apiService.getCategories() }
}

suspend fun getProducts(categoryId: String, sort: String): Resource<ProductApiModel> =
safeApiCall { apiService.getProducts(categoryId, sort) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@ package com.muhammedesadcomert.shopping.ui.home

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.muhammedesadcomert.shopping.databinding.CategoryItemBinding
import com.muhammedesadcomert.shopping.ui.home.CategoryAdapter.CategoryViewHolder
import com.muhammedesadcomert.shopping.ui.home.model.Category

class CategoryAdapter(
private val categories: List<Category>,
private val onItemClicked: (Category) -> Unit,
) : RecyclerView.Adapter<CategoryViewHolder>() {
class CategoryAdapter(private val onItemClicked: (Category) -> Unit) :
ListAdapter<Category, CategoryViewHolder>(DIFF_CALLBACK) {

inner class CategoryViewHolder(private val binding: CategoryItemBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(category: Category) {
with(binding) {
Glide.with(itemView).load(category.icon).into(categoryIcon)
categoryName.text = category.name
Glide.with(itemView).load(category.icon!!).into(categoryIcon)
}
}
}
Expand All @@ -30,12 +30,22 @@ class CategoryAdapter(
}

override fun onBindViewHolder(holder: CategoryViewHolder, position: Int) {
val category = categories[position]
val category = currentList[position]
holder.bind(category)
holder.itemView.setOnClickListener {
onItemClicked(category)
}
}

override fun getItemCount() = categories.size
}
companion object {
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Category>() {
override fun areItemsTheSame(oldItem: Category, newItem: Category): Boolean {
return oldItem == newItem
}

override fun areContentsTheSame(oldItem: Category, newItem: Category): Boolean {
return oldItem == newItem
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import com.muhammedesadcomert.shopping.databinding.FragmentHomeBinding
import com.muhammedesadcomert.shopping.ui.home.model.Category
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
Expand All @@ -17,11 +17,12 @@ class HomeFragment : Fragment() {
private val binding get() = _binding!!

private val viewModel: HomeViewModel by viewModels()
private lateinit var categories: List<Category>

private lateinit var categoryAdapter: CategoryAdapter
private lateinit var productAdapter: ProductAdapter

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
Expand All @@ -30,18 +31,22 @@ class HomeFragment : Fragment() {

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
getCategories()
initCategoryAdapter()
submitCategories()
initProductAdapter()
submitProducts()
}

private fun getCategories() {
viewModel.categories.observe(viewLifecycleOwner) {
categories = it
initCategoryAdapter()
private fun submitCategories() {
viewModel.categories.observe(viewLifecycleOwner) { categories ->
categoryAdapter.submitList(categories)
}
}

private fun initCategoryAdapter() {
val categoryAdapter = CategoryAdapter(categories) { category ->
categoryAdapter = CategoryAdapter { category ->
binding.textViewCategory.text = category.name
viewModel.getProducts(category.categoryId)
}

binding.recyclerViewCategories.apply {
Expand All @@ -50,8 +55,27 @@ class HomeFragment : Fragment() {
}
}

private fun submitProducts() {
viewModel.products.observe(viewLifecycleOwner) { products ->
productAdapter.submitList(products)
}
}

private fun initProductAdapter() {
productAdapter = ProductAdapter { product ->
findNavController().navigate(
HomeFragmentDirections.actionHomeFragmentToProductDetailFragment(product.id!!)
)
}

binding.recyclerViewProducts.apply {
adapter = productAdapter
setHasFixedSize(true)
}
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package com.muhammedesadcomert.shopping.ui.home

import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.muhammedesadcomert.shopping.common.util.Constant.DEFAULT_CATEGORY
import com.muhammedesadcomert.shopping.common.util.Constant.DEFAULT_SORT
import com.muhammedesadcomert.shopping.common.util.Resource
import com.muhammedesadcomert.shopping.data.repository.ProductRepository
import com.muhammedesadcomert.shopping.ui.home.model.Category
import com.muhammedesadcomert.shopping.ui.home.model.Product
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject
Expand All @@ -17,8 +21,12 @@ class HomeViewModel @Inject constructor(private val productRepository: ProductRe
private var _categories: MutableLiveData<List<Category>> = MutableLiveData()
val categories: LiveData<List<Category>> get() = _categories

private var _products: MutableLiveData<List<Product>> = MutableLiveData()
val products: LiveData<List<Product>> get() = _products

init {
getCategories()
getProducts()
}

private fun getCategories() {
Expand All @@ -30,9 +38,26 @@ class HomeViewModel @Inject constructor(private val productRepository: ProductRe
}
}
is Resource.Failure -> {
Log.e("Failure", resource.errorMessage)
}
else -> {}
}
}
}

fun getProducts(categoryId: String = DEFAULT_CATEGORY, sort: String = DEFAULT_SORT) {
viewModelScope.launch {
when (val resource = productRepository.getProducts(categoryId, sort)) {
is Resource.Success -> {
resource.data?.let {
_products.postValue(it.products)
}
}
is Resource.Failure -> {
Log.e("Failure", resource.errorMessage)
}
else -> {}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.muhammedesadcomert.shopping.ui.home

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.muhammedesadcomert.shopping.databinding.ProductItemBinding
import com.muhammedesadcomert.shopping.ui.home.ProductAdapter.ProductViewHolder
import com.muhammedesadcomert.shopping.ui.home.model.Product

class ProductAdapter(private val onItemClicked: (Product) -> Unit) :
ListAdapter<Product, ProductViewHolder>(DIFF_CALLBACK) {
inner class ProductViewHolder(private val binding: ProductItemBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(product: Product) {
with(binding) {
textViewProductTitle.text = product.title
textViewProductPrice.text = "$".plus(product.price.toString())
Glide.with(itemView).load(product.featuredImage!!.t).into(imageViewProductImage)
}
}
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductViewHolder {
return ProductViewHolder(
ProductItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
}

override fun onBindViewHolder(holder: ProductViewHolder, position: Int) {
val product = currentList[position]
holder.bind(product)
holder.itemView.setOnClickListener {
onItemClicked(product)
}
}

companion object {
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Product>() {
override fun areItemsTheSame(oldItem: Product, newItem: Product): Boolean {
return oldItem == newItem
}

override fun areContentsTheSame(oldItem: Product, newItem: Product): Boolean {
return oldItem == newItem
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,26 @@ data class CategoryApiModel(
@SerializedName("success")
val success: Boolean,
@SerializedName("data")
val categories: List<Category>,
val categories: List<Category> = arrayListOf(),
)

data class Category(
@SerializedName("categoryId")
val categoryId: String,
@SerializedName("createDate")
val createDate: String,
@SerializedName("icon")
val icon: String,
@SerializedName("isActive")
val isActive: Boolean,
@SerializedName("name")
val name: String,
val name: String? = null,
@SerializedName("icon")
val icon: String? = null,
@SerializedName("orderIndex")
val orderIndex: Int,
@SerializedName("subCategories")
val subCategories: List<Any>,
@SerializedName("totalProducts")
val totalProducts: Int,
val orderIndex: Int? = null,
@SerializedName("createDate")
val createDate: String? = null,
@SerializedName("updateDate")
val updateDate: String,
)
val updateDate: String? = null,
@SerializedName("totalProducts")
val totalProducts: Int? = null,
@SerializedName("isActive")
val isActive: Boolean? = null,
@SerializedName("subCategories")
val subCategories: ArrayList<String> = arrayListOf(),
)
Loading

0 comments on commit 1657b69

Please sign in to comment.