diff --git a/app/src/main/java/com/sopt/geonppang/data/datasource/remote/FilterDataSource.kt b/app/src/main/java/com/sopt/geonppang/data/datasource/remote/FilterDataSource.kt new file mode 100644 index 00000000..3d90febd --- /dev/null +++ b/app/src/main/java/com/sopt/geonppang/data/datasource/remote/FilterDataSource.kt @@ -0,0 +1,14 @@ +package com.sopt.geonppang.data.datasource.remote + +import com.sopt.geonppang.data.model.request.RequestFilter +import com.sopt.geonppang.data.model.response.ResponseFilter +import com.sopt.geonppang.data.service.FilterService +import javax.inject.Inject + +class FilterDataSource @Inject constructor( + private val filterService: FilterService, +) { + suspend fun setFilter( + requestFilter: RequestFilter + ): ResponseFilter = filterService.setFilter(requestFilter) +} diff --git a/app/src/main/java/com/sopt/geonppang/data/model/request/RequestFilter.kt b/app/src/main/java/com/sopt/geonppang/data/model/request/RequestFilter.kt new file mode 100644 index 00000000..886746f0 --- /dev/null +++ b/app/src/main/java/com/sopt/geonppang/data/model/request/RequestFilter.kt @@ -0,0 +1,25 @@ +package com.sopt.geonppang.data.model.request + +import kotlinx.serialization.Serializable + +@Serializable +data class RequestFilter( + val mainPurpose: String, + val breadType: BreadType, + val nutrientType: NutrientType +) { + @Serializable + data class BreadType( + val isGlutenFree: Boolean, + val isVegan: Boolean, + val isNutFree: Boolean, + val isSugarFree: Boolean, + ) + + @Serializable + data class NutrientType( + val isNutrientOpen: Boolean, + val isIngredientOpen: Boolean, + val isNotOpen: Boolean, + ) +} diff --git a/app/src/main/java/com/sopt/geonppang/data/model/response/ResponseFilter.kt b/app/src/main/java/com/sopt/geonppang/data/model/response/ResponseFilter.kt new file mode 100644 index 00000000..4f963ac8 --- /dev/null +++ b/app/src/main/java/com/sopt/geonppang/data/model/response/ResponseFilter.kt @@ -0,0 +1,53 @@ +package com.sopt.geonppang.data.model.response + +import com.sopt.geonppang.domain.model.SelectedFilter +import kotlinx.serialization.Serializable + +@Serializable +data class ResponseFilter( + val code: Int, + val data: Data, + val message: String +) { + @Serializable + data class Data( + val breadType: BreadType, + val mainPurpose: String, + val memberId: Int, + val nutrientType: NutrientType + ) + + @Serializable + data class BreadType( + val breadTypeId: Int, + val breadTypeName: String, + val isGlutenFree: Boolean, + val isNutFree: Boolean, + val isSugarFree: Boolean, + val isVegan: Boolean + ) + + @Serializable + data class NutrientType( + val isIngredientOpen: Boolean, + val isNotOpen: Boolean, + val isNutrientOpen: Boolean, + val nutrientTypeId: Int, + val nutrientTypeName: String + ) + + fun toSelectedFilter() = SelectedFilter( + mainPurpose = data.mainPurpose, + breadType = SelectedFilter.BreadType( + isGlutenFree = data.breadType.isGlutenFree, + isVegan = data.breadType.isVegan, + isNutFree = data.breadType.isNutFree, + isSugarFree = data.breadType.isSugarFree + ), + nutrientType = SelectedFilter.NutrientType( + isIngredientOpen = data.nutrientType.isIngredientOpen, + isNotOpen = data.nutrientType.isNotOpen, + isNutrientOpen = data.nutrientType.isNutrientOpen + ) + ) +} diff --git a/app/src/main/java/com/sopt/geonppang/data/repository/FilterRepositoryImpl.kt b/app/src/main/java/com/sopt/geonppang/data/repository/FilterRepositoryImpl.kt new file mode 100644 index 00000000..29f50bcb --- /dev/null +++ b/app/src/main/java/com/sopt/geonppang/data/repository/FilterRepositoryImpl.kt @@ -0,0 +1,16 @@ +package com.sopt.geonppang.data.repository + +import com.sopt.geonppang.data.datasource.remote.FilterDataSource +import com.sopt.geonppang.data.model.request.RequestFilter +import com.sopt.geonppang.domain.model.SelectedFilter +import com.sopt.geonppang.domain.repository.FilterRepository +import javax.inject.Inject + +class FilterRepositoryImpl @Inject constructor( + private val filterDataSource: FilterDataSource +) : FilterRepository { + override suspend fun setFilter(requestFilter: RequestFilter): Result = + runCatching { + filterDataSource.setFilter(requestFilter).toSelectedFilter() + } +} diff --git a/app/src/main/java/com/sopt/geonppang/data/service/FilterService.kt b/app/src/main/java/com/sopt/geonppang/data/service/FilterService.kt new file mode 100644 index 00000000..adf331c8 --- /dev/null +++ b/app/src/main/java/com/sopt/geonppang/data/service/FilterService.kt @@ -0,0 +1,13 @@ +package com.sopt.geonppang.data.service + +import com.sopt.geonppang.data.model.request.RequestFilter +import com.sopt.geonppang.data.model.response.ResponseFilter +import retrofit2.http.Body +import retrofit2.http.POST + +interface FilterService { + @POST("member/types") + suspend fun setFilter( + @Body requestFilter: RequestFilter + ): ResponseFilter +} diff --git a/app/src/main/java/com/sopt/geonppang/di/RepositoryModule.kt b/app/src/main/java/com/sopt/geonppang/di/RepositoryModule.kt index e957abec..2e27082c 100644 --- a/app/src/main/java/com/sopt/geonppang/di/RepositoryModule.kt +++ b/app/src/main/java/com/sopt/geonppang/di/RepositoryModule.kt @@ -3,12 +3,14 @@ package com.sopt.geonppang.di import com.sopt.geonppang.data.repository.BakeryRepositoryImpl import com.sopt.geonppang.data.repository.DetailRepositoryImpl import com.sopt.geonppang.data.repository.DummyRepositoryImpl +import com.sopt.geonppang.data.repository.FilterRepositoryImpl import com.sopt.geonppang.data.repository.HomeRepositoryImpl import com.sopt.geonppang.data.repository.MypageRepositoryImpl import com.sopt.geonppang.data.repository.SearchRepositoryImpl import com.sopt.geonppang.domain.repository.BakeryRepository import com.sopt.geonppang.domain.repository.DetailRepository import com.sopt.geonppang.domain.repository.DummyRepository +import com.sopt.geonppang.domain.repository.FilterRepository import com.sopt.geonppang.domain.repository.HomeRepository import com.sopt.geonppang.domain.repository.MypageRepository import com.sopt.geonppang.domain.repository.SearchRepository @@ -56,4 +58,10 @@ interface RepositoryModule { fun bindDetailRepository( detailRepositoryImpl: DetailRepositoryImpl, ): DetailRepository + + @Binds + @Singleton + fun bindFilterRepository( + filterRepositoryImpl: FilterRepositoryImpl, + ): FilterRepository } diff --git a/app/src/main/java/com/sopt/geonppang/di/ServiceModule.kt b/app/src/main/java/com/sopt/geonppang/di/ServiceModule.kt index 0b23f7c7..fcc7b157 100644 --- a/app/src/main/java/com/sopt/geonppang/di/ServiceModule.kt +++ b/app/src/main/java/com/sopt/geonppang/di/ServiceModule.kt @@ -3,6 +3,7 @@ package com.sopt.geonppang.di import com.sopt.geonppang.data.service.BakeryService import com.sopt.geonppang.data.service.DetailService import com.sopt.geonppang.data.service.DummyService +import com.sopt.geonppang.data.service.FilterService import com.sopt.geonppang.data.service.HomeService import com.sopt.geonppang.data.service.MypageService import com.sopt.geonppang.data.service.SearchService @@ -45,4 +46,9 @@ object ServiceModule { @Provides fun provideDetailService(retrofit: Retrofit): DetailService = retrofit.create(DetailService::class.java) + + @Singleton + @Provides + fun provideFilterService(retrofit: Retrofit): FilterService = + retrofit.create(FilterService::class.java) } diff --git a/app/src/main/java/com/sopt/geonppang/domain/model/SelectedFilter.kt b/app/src/main/java/com/sopt/geonppang/domain/model/SelectedFilter.kt new file mode 100644 index 00000000..05a61375 --- /dev/null +++ b/app/src/main/java/com/sopt/geonppang/domain/model/SelectedFilter.kt @@ -0,0 +1,20 @@ +package com.sopt.geonppang.domain.model + +data class SelectedFilter( + val mainPurpose: String, + val breadType: BreadType, + val nutrientType: NutrientType +) { + data class BreadType( + val isGlutenFree: Boolean, + val isVegan: Boolean, + val isNutFree: Boolean, + val isSugarFree: Boolean, + ) + + data class NutrientType( + val isIngredientOpen: Boolean, + val isNotOpen: Boolean, + val isNutrientOpen: Boolean + ) +} diff --git a/app/src/main/java/com/sopt/geonppang/domain/repository/FilterRepository.kt b/app/src/main/java/com/sopt/geonppang/domain/repository/FilterRepository.kt new file mode 100644 index 00000000..7e408ae4 --- /dev/null +++ b/app/src/main/java/com/sopt/geonppang/domain/repository/FilterRepository.kt @@ -0,0 +1,10 @@ +package com.sopt.geonppang.domain.repository + +import com.sopt.geonppang.data.model.request.RequestFilter +import com.sopt.geonppang.domain.model.SelectedFilter + +interface FilterRepository { + suspend fun setFilter( + requestFilter: RequestFilter + ): Result +} diff --git a/app/src/main/java/com/sopt/geonppang/presentation/filter/FilterActivity.kt b/app/src/main/java/com/sopt/geonppang/presentation/filter/FilterActivity.kt index 70b0a1be..8dc5ffb4 100644 --- a/app/src/main/java/com/sopt/geonppang/presentation/filter/FilterActivity.kt +++ b/app/src/main/java/com/sopt/geonppang/presentation/filter/FilterActivity.kt @@ -6,7 +6,9 @@ import androidx.lifecycle.ViewModelProvider import com.sopt.geonppang.R import com.sopt.geonppang.databinding.ActivityFilterBinding import com.sopt.geonppang.util.binding.BindingActivity +import dagger.hilt.android.AndroidEntryPoint +@AndroidEntryPoint class FilterActivity : BindingActivity(R.layout.activity_filter) { private lateinit var viewModel: FilterViewModel private lateinit var adapter: FilterViewPagerAdapter @@ -44,6 +46,7 @@ class FilterActivity : BindingActivity(R.layout.activity_ binding.btnFilterNext.setOnClickListener { when (binding.vpFilterContainer.currentItem) { 2 -> { + viewModel.setFilter() startActivity(Intent(this, WelcomeActivity::class.java)) } diff --git a/app/src/main/java/com/sopt/geonppang/presentation/filter/FilterViewModel.kt b/app/src/main/java/com/sopt/geonppang/presentation/filter/FilterViewModel.kt index ddb06e0d..74db7b3c 100644 --- a/app/src/main/java/com/sopt/geonppang/presentation/filter/FilterViewModel.kt +++ b/app/src/main/java/com/sopt/geonppang/presentation/filter/FilterViewModel.kt @@ -4,11 +4,27 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.sopt.geonppang.data.model.request.RequestFilter +import com.sopt.geonppang.domain.model.SelectedFilter +import com.sopt.geonppang.domain.repository.FilterRepository import com.sopt.geonppang.presentation.type.BreadFilterType import com.sopt.geonppang.presentation.type.MainPurposeType import com.sopt.geonppang.presentation.type.NutrientFilterType +import com.sopt.geonppang.util.UiState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class FilterViewModel @Inject constructor( + private val filterRepository: FilterRepository +) : ViewModel() { + private val _selectedFilterState = MutableStateFlow>(UiState.Loading) + val selectedFilterState get() = _selectedFilterState.asStateFlow() -class FilterViewModel : ViewModel() { private val _mainPurpose: MutableLiveData = MutableLiveData() val mainPurpose: LiveData = _mainPurpose @@ -58,4 +74,35 @@ class FilterViewModel : ViewModel() { value = nutrientMap.any { it.value } } } + + fun setFilter() { + viewModelScope.launch { + _mainPurpose.value?.let { + RequestFilter( + it.name, + RequestFilter.BreadType( + breadFilterType.value?.get(BreadFilterType.GLUTENFREE) == true, + breadFilterType.value?.get(BreadFilterType.VEGAN) == true, + breadFilterType.value?.get(BreadFilterType.NUTFREE) == true, + breadFilterType.value?.get(BreadFilterType.SUGARFREE) == true, + ), + RequestFilter.NutrientType( + nutrientFilterType.value?.get(NutrientFilterType.NUTRIENT) == true, + nutrientFilterType.value?.get(NutrientFilterType.INGREDIENT) == true, + nutrientFilterType.value?.get(NutrientFilterType.NOT) == true, + ) + ) + }?.let { + filterRepository.setFilter( + it + ) + .onSuccess { selectedFilter -> + _selectedFilterState.value = UiState.Success(selectedFilter) + } + .onFailure { throwable -> + _selectedFilterState.value = UiState.Error(throwable.message) + } + } + } + } }