Skip to content

Commit

Permalink
feat (BookmarkRecipe): Create feature Bookmark
Browse files Browse the repository at this point in the history
  • Loading branch information
faizul14 committed Jan 19, 2024
1 parent 3345ac0 commit 00f44b1
Show file tree
Hide file tree
Showing 20 changed files with 466 additions and 54 deletions.
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
android:supportsRtl="true"
android:theme="@style/Theme.MealRecipeApp"
tools:targetApi="31">
<activity
android:name=".presentation.bookmark.BookMarkActivity"
android:exported="false" />
<activity
android:name=".presentation.search.SearchActivity"
android:exported="false" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package com.faezolmp.mealrecipeapp.core.data

import com.faezolmp.mealrecipeapp.core.data.source.local.entity.EntityMeal
import com.faezolmp.mealrecipeapp.core.data.source.local.room.DaoMeal
import com.faezolmp.mealrecipeapp.core.data.source.remote.RemoteDataSource
import com.faezolmp.mealrecipeapp.core.data.source.remote.network.ApiResponse
import com.faezolmp.mealrecipeapp.core.data.source.remote.response.MealsItemDetail
import com.faezolmp.mealrecipeapp.core.domain.model.ModelDetailDataMeal
import com.faezolmp.mealrecipeapp.core.domain.model.ModelListCategory
import com.faezolmp.mealrecipeapp.core.domain.model.ModelListMealBookMark
import com.faezolmp.mealrecipeapp.core.domain.model.ModelListMealByCategory
import com.faezolmp.mealrecipeapp.core.domain.repository.Repository
import com.faezolmp.mealrecipeapp.core.helper.DataMapper
Expand All @@ -16,7 +19,8 @@ import kotlinx.coroutines.flow.flowOf
import javax.inject.Inject

class ImplementRepository @Inject constructor(
private val remoteDataSource: RemoteDataSource
private val remoteDataSource: RemoteDataSource,
private val daoMeal: DaoMeal,
) : Repository {
override fun sampleinterface() = "retunvaluesample"
override fun getListCategory(): Flow<Resource<List<ModelListCategory>>> {
Expand Down Expand Up @@ -87,4 +91,30 @@ class ImplementRepository @Inject constructor(
}
}
}

override fun getDataMailBookmark(): Flow<Resource<List<ModelListMealBookMark>>> {
return flow {
emit(Resource.Loading())
try {
val dataResponse = daoMeal.getListDataMeal().first()
if (dataResponse.isNotEmpty()){
val data = DataMapper.mapperDataListBookMarkFromDataLayerToDomainLayer(dataResponse)
val dataResult = flowOf(Resource.Success(data))
emitAll(dataResult)
}else{
emit(Resource.Loading())
}
}catch (e : Exception){
emit(Resource.Error(e.message.toString()))
}
}
}

override suspend fun addDataMealBooMark(dataBookMarkMeal: ModelListMealBookMark) {
daoMeal.addMeal(DataMapper.mapperDataListBookMarkFromDomainLyerToDataLayer(dataBookMarkMeal))
}

override fun deleteDataMealBooMark(dataBookMarkMeal: ModelListMealBookMark) {
daoMeal.deleteMeal(DataMapper.mapperDataListBookMarkFromDomainLyerToDataLayer(dataBookMarkMeal))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.faezolmp.mealrecipeapp.core.data.source.local

import com.faezolmp.mealrecipeapp.core.data.source.local.entity.EntityMeal
import com.faezolmp.mealrecipeapp.core.data.source.local.room.DaoMeal
import kotlinx.coroutines.flow.Flow
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class LocalDataSource @Inject constructor(private val daoMeal: DaoMeal) {
private val executorService: ExecutorService = Executors.newSingleThreadExecutor()

fun getDataListMeal(): Flow<List<EntityMeal>> = daoMeal.getListDataMeal()

suspend fun addDataMeal(dataMeal: EntityMeal) = daoMeal.addMeal(dataMeal)
fun deleteDataMeal(dataMeal: EntityMeal) = executorService.execute{
daoMeal.deleteMeal(dataMeal)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.faezolmp.mealrecipeapp.core.data.source.local.entity

import android.os.Parcelable
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.parcelize.Parcelize

@Entity
@Parcelize
data class EntityMeal(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
var id: Int = 0,
@ColumnInfo(name = "strMealThumb")
val strMealThumb: String? = null,
@ColumnInfo(name = "idMeal")
val idMeal: String? = null,
@ColumnInfo(name = "strMeal")
val strMeal: String? = null
): Parcelable
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.faezolmp.mealrecipeapp.core.data.source.local.room

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.faezolmp.mealrecipeapp.core.data.source.local.entity.EntityMeal
import kotlinx.coroutines.flow.Flow

@Dao
interface DaoMeal {
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun addMeal(entityMeal: EntityMeal)

@Delete
fun deleteMeal(entityMeal: EntityMeal)

@Query("SELECT * FROM EntityMeal")
fun getListDataMeal(): Flow<List<EntityMeal>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.faezolmp.mealrecipeapp.core.data.source.local.room

import androidx.room.Database
import androidx.room.RoomDatabase
import com.faezolmp.mealrecipeapp.core.data.source.local.entity.EntityMeal

@Database(entities = [EntityMeal::class], version = 1, exportSchema = false)
abstract class DatabaseMeal: RoomDatabase() {
abstract fun daoMeal(): DaoMeal
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.faezolmp.mealrecipeapp.core.di

import android.content.Context
import androidx.room.Room
import com.faezolmp.mealrecipeapp.core.data.source.local.room.DaoMeal
import com.faezolmp.mealrecipeapp.core.data.source.local.room.DatabaseMeal
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
class DatabaseModule {
@Singleton
@Provides
fun provideDatabase(@ApplicationContext context: Context): DatabaseMeal = Room.databaseBuilder(
context,
DatabaseMeal::class.java, "Enstore.db"
).fallbackToDestructiveMigration().build()

@Provides
fun provideDaoMeal(database: DatabaseMeal): DaoMeal = database.daoMeal()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.faezolmp.mealrecipeapp.core.domain.model

import android.os.Parcelable
import kotlinx.parcelize.Parcelize

@Parcelize
data class ModelListMealBookMark(
val id: Int = 0,
val strMealThumb: String? = null,
val idMeal: String? = null,
val strMeal: String? = null
) : Parcelable
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.faezolmp.mealrecipeapp.core.domain.repository

import com.faezolmp.mealrecipeapp.core.data.Resource
import com.faezolmp.mealrecipeapp.core.data.source.local.entity.EntityMeal
import com.faezolmp.mealrecipeapp.core.data.source.remote.response.MealsItemDetail
import com.faezolmp.mealrecipeapp.core.domain.model.ModelDetailDataMeal
import com.faezolmp.mealrecipeapp.core.domain.model.ModelListCategory
import com.faezolmp.mealrecipeapp.core.domain.model.ModelListMealBookMark
import com.faezolmp.mealrecipeapp.core.domain.model.ModelListMealByCategory
import kotlinx.coroutines.flow.Flow

Expand All @@ -12,4 +14,8 @@ interface Repository {
fun getListCategory(): Flow<Resource<List<ModelListCategory>>>
fun getDataListByCategoryy(category: String, meal: String): Flow<Resource<List<ModelListMealByCategory>>>
fun getDetailMealBy(idmeal: String): Flow<Resource<List<ModelDetailDataMeal>>>

fun getDataMailBookmark(): Flow<Resource<List<ModelListMealBookMark>>>
suspend fun addDataMealBooMark(entityMeal: ModelListMealBookMark)
fun deleteDataMealBooMark(dataBooMarkMeal: ModelListMealBookMark)
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.faezolmp.mealrecipeapp.core.domain.usecase

import com.faezolmp.mealrecipeapp.core.data.Resource
import com.faezolmp.mealrecipeapp.core.data.source.local.entity.EntityMeal
import com.faezolmp.mealrecipeapp.core.domain.model.ModelDetailDataMeal
import com.faezolmp.mealrecipeapp.core.domain.model.ModelListCategory
import com.faezolmp.mealrecipeapp.core.domain.model.ModelListMealBookMark
import com.faezolmp.mealrecipeapp.core.domain.model.ModelListMealByCategory
import com.faezolmp.mealrecipeapp.core.domain.repository.Repository
import kotlinx.coroutines.flow.Flow
Expand All @@ -29,4 +31,16 @@ class ImplementUseCase @Inject constructor(
override fun getDetailMealBy(idmeal: String): Flow<Resource<List<ModelDetailDataMeal>>> {
return repository.getDetailMealBy(idmeal)
}

override fun getDataMailBookmark(): Flow<Resource<List<ModelListMealBookMark>>> {
return repository.getDataMailBookmark()
}

override suspend fun addDataMealBooMark(dataBooMarkMeal: ModelListMealBookMark) {
repository.addDataMealBooMark(dataBooMarkMeal)
}

override fun deleteDataMealBooMark(dataBooMarkMeal: ModelListMealBookMark) {
repository.deleteDataMealBooMark(dataBooMarkMeal)
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.faezolmp.mealrecipeapp.core.domain.usecase

import com.faezolmp.mealrecipeapp.core.data.Resource
import com.faezolmp.mealrecipeapp.core.data.source.local.entity.EntityMeal
import com.faezolmp.mealrecipeapp.core.domain.model.ModelDetailDataMeal
import com.faezolmp.mealrecipeapp.core.domain.model.ModelListCategory
import com.faezolmp.mealrecipeapp.core.domain.model.ModelListMealBookMark
import com.faezolmp.mealrecipeapp.core.domain.model.ModelListMealByCategory
import kotlinx.coroutines.flow.Flow

Expand All @@ -11,5 +13,8 @@ interface UseCase {
fun getListCategory(): Flow<Resource<List<ModelListCategory>>>
fun getDataListBy(category: String, meal: String): Flow<Resource<List<ModelListMealByCategory>>>
fun getDetailMealBy(idmeal: String): Flow<Resource<List<ModelDetailDataMeal>>>
fun getDataMailBookmark(): Flow<Resource<List<ModelListMealBookMark>>>

suspend fun addDataMealBooMark(dataBooMarkMeal: ModelListMealBookMark)
fun deleteDataMealBooMark(dataBooMarkMeal: ModelListMealBookMark)
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.faezolmp.mealrecipeapp.core.helper

import com.faezolmp.mealrecipeapp.core.data.source.local.entity.EntityMeal
import com.faezolmp.mealrecipeapp.core.data.source.remote.response.CategoriesItem
import com.faezolmp.mealrecipeapp.core.data.source.remote.response.MealsItem
import com.faezolmp.mealrecipeapp.core.data.source.remote.response.MealsItemDetail
import com.faezolmp.mealrecipeapp.core.domain.model.ModelDetailDataMeal
import com.faezolmp.mealrecipeapp.core.domain.model.ModelListCategory
import com.faezolmp.mealrecipeapp.core.domain.model.ModelListMealBookMark
import com.faezolmp.mealrecipeapp.core.domain.model.ModelListMealByCategory

object DataMapper {
Expand Down Expand Up @@ -101,4 +103,41 @@ object DataMapper {

return dataResult
}

fun mapperDataListBookMarkFromDataLayerToDomainLayer(input: List<EntityMeal>): List<ModelListMealBookMark> {
var dataResult = ArrayList<ModelListMealBookMark>()
input.map {
val data = ModelListMealBookMark(
id =it.id,
strMealThumb = it.strMealThumb,
idMeal = it.idMeal,
strMeal = it.strMeal,
)
dataResult.add(data)
}
return dataResult
}

fun mapperDataListBookMarkFromDomainLyerToDataLayer(input: ModelListMealBookMark): EntityMeal {
val data = EntityMeal(
id =input.id,
strMealThumb = input.strMealThumb,
idMeal = input.idMeal,
strMeal = input.strMeal,
)
return data
}

fun mapperHelper(input: List<ModelListMealBookMark>): List<ModelListMealByCategory>{
val resultData = ArrayList<ModelListMealByCategory>()
input.map {
val data = ModelListMealByCategory(
strMealThumb = it.strMealThumb,
idMeal = it.idMeal,
strMeal = it.strMeal,
)
resultData.add(data)
}
return resultData
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.faezolmp.mealrecipeapp.presentation.bookmark

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.activity.viewModels
import androidx.recyclerview.widget.GridLayoutManager
import com.faezolmp.mealrecipeapp.R
import com.faezolmp.mealrecipeapp.core.data.Resource
import com.faezolmp.mealrecipeapp.core.helper.DataMapper
import com.faezolmp.mealrecipeapp.core.ui.ListDataByAdapter
import com.faezolmp.mealrecipeapp.databinding.ActivityBookMarkBinding
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class BookMarkActivity : AppCompatActivity() {
private lateinit var binding: ActivityBookMarkBinding
private val viewModel: BookMarkViewModel by viewModels()
private val listBookMarkAdapter by lazy { ListDataByAdapter() }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityBookMarkBinding.inflate(layoutInflater)
setContentView(binding.root)
setUpInit()
observerViewModel()
}

private fun observerViewModel() {
viewModel.getListDataBookMark.observe(this){dataMeal ->
when (dataMeal) {
is Resource.Loading -> {
// loading(true)
}

is Resource.Error -> {
Toast.makeText(
this,
"Error: ${dataMeal.message.toString()}",
Toast.LENGTH_SHORT
).show()
}

is Resource.Success -> {
dataMeal.data?.let { listBookMarkAdapter.setData(DataMapper.mapperHelper(it)) }
binding.rvBokmark.adapter = listBookMarkAdapter
listBookMarkAdapter.notifyDataSetChanged()
// loading(false)
}
}
}
}

private fun setUpInit() {
binding.rvBokmark.apply {
layoutManager = GridLayoutManager(
this@BookMarkActivity,
2
)
setHasFixedSize(true)
adapter = listBookMarkAdapter
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.faezolmp.mealrecipeapp.presentation.bookmark

import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import com.faezolmp.mealrecipeapp.core.domain.usecase.UseCase
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject

@HiltViewModel
class BookMarkViewModel @Inject constructor(private val useCase: UseCase): ViewModel() {
val getListDataBookMark = useCase.getDataMailBookmark().asLiveData()
}
Loading

0 comments on commit 00f44b1

Please sign in to comment.