diff --git a/app/src/main/java/org/sopt/pingle/data/datasource/remote/PlanRemoteDataSource.kt b/app/src/main/java/org/sopt/pingle/data/datasource/remote/PlanRemoteDataSource.kt new file mode 100644 index 00000000..9d5be8f0 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/data/datasource/remote/PlanRemoteDataSource.kt @@ -0,0 +1,8 @@ +package org.sopt.pingle.data.datasource.remote + +import org.sopt.pingle.data.model.remote.response.ResponsePlanDto +import org.sopt.pingle.util.base.BaseResponse + +interface PlanRemoteDataSource { + suspend fun getPlanLocation(searchWord: String): BaseResponse> +} diff --git a/app/src/main/java/org/sopt/pingle/data/datasourceimpl/remote/PlanRemoteDataSourceImpl.kt b/app/src/main/java/org/sopt/pingle/data/datasourceimpl/remote/PlanRemoteDataSourceImpl.kt new file mode 100644 index 00000000..75815bfb --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/data/datasourceimpl/remote/PlanRemoteDataSourceImpl.kt @@ -0,0 +1,14 @@ +package org.sopt.pingle.data.datasourceimpl.remote + +import javax.inject.Inject +import org.sopt.pingle.data.datasource.remote.PlanRemoteDataSource +import org.sopt.pingle.data.model.remote.response.ResponsePlanDto +import org.sopt.pingle.data.service.PlanService +import org.sopt.pingle.util.base.BaseResponse + +class PlanRemoteDataSourceImpl @Inject constructor( + private val planService: PlanService +) : PlanRemoteDataSource { + override suspend fun getPlanLocation(searchWord: String): BaseResponse> = + planService.getPlanLocationList(searchWord = searchWord) +} diff --git a/app/src/main/java/org/sopt/pingle/data/model/remote/request/RequestPlanDto.kt b/app/src/main/java/org/sopt/pingle/data/model/remote/request/RequestPlanDto.kt new file mode 100644 index 00000000..cf22aaa0 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/data/model/remote/request/RequestPlanDto.kt @@ -0,0 +1,10 @@ +package org.sopt.pingle.data.model.remote.request + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class RequestPlanDto( + @SerialName("search") + val search: String +) diff --git a/app/src/main/java/org/sopt/pingle/data/model/remote/response/ResponsePlanDto.kt b/app/src/main/java/org/sopt/pingle/data/model/remote/response/ResponsePlanDto.kt new file mode 100644 index 00000000..f2988e37 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/data/model/remote/response/ResponsePlanDto.kt @@ -0,0 +1,26 @@ +package org.sopt.pingle.data.model.remote.response + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import org.sopt.pingle.domain.model.PlanLocationEntity + +@Serializable +data class ResponsePlanDto( + @SerialName("x") + val xCoordinate: Double, + @SerialName("y") + val yCoordinate: Double, + @SerialName("location") + val locationName: String, + @SerialName("address") + val locationAddress: String, + @SerialName("roadAddress") + val locationRoadAddress: String +) { + fun toPlanLocationEntity() = PlanLocationEntity( + location = locationName, + address = locationAddress, + x = xCoordinate, + y = yCoordinate + ) +} diff --git a/app/src/main/java/org/sopt/pingle/data/repository/PlanRepositoryImpl.kt b/app/src/main/java/org/sopt/pingle/data/repository/PlanRepositoryImpl.kt new file mode 100644 index 00000000..9d43e791 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/data/repository/PlanRepositoryImpl.kt @@ -0,0 +1,22 @@ +package org.sopt.pingle.data.repository + +import javax.inject.Inject +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import org.sopt.pingle.data.datasource.remote.PlanRemoteDataSource +import org.sopt.pingle.domain.model.PlanLocationEntity +import org.sopt.pingle.domain.repository.PlanRepository + +class PlanRepositoryImpl @Inject constructor( + private val planRemoteDataSource: PlanRemoteDataSource +) : PlanRepository { + override suspend fun getPlanLocationList(searchWord: String): Flow> = + flow { + val result = runCatching { + planRemoteDataSource.getPlanLocation(searchWord = searchWord).data.map { planLocation -> + planLocation.toPlanLocationEntity() + } + } + emit(result.getOrThrow()) + } +} diff --git a/app/src/main/java/org/sopt/pingle/data/service/PlanService.kt b/app/src/main/java/org/sopt/pingle/data/service/PlanService.kt new file mode 100644 index 00000000..060cd8a3 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/data/service/PlanService.kt @@ -0,0 +1,19 @@ +package org.sopt.pingle.data.service + +import org.sopt.pingle.data.model.remote.response.ResponsePlanDto +import org.sopt.pingle.util.base.BaseResponse +import retrofit2.http.GET +import retrofit2.http.Query + +interface PlanService { + @GET("$VERSION/$LOCATION") + suspend fun getPlanLocationList( + @Query(SEARCH_WORD) searchWord: String + ): BaseResponse> + + companion object { + const val VERSION = "v1" + const val LOCATION = "location" + const val SEARCH_WORD = "search" + } +} diff --git a/app/src/main/java/org/sopt/pingle/di/DataSourceModule.kt b/app/src/main/java/org/sopt/pingle/di/DataSourceModule.kt index 6124d187..d1e36f6d 100644 --- a/app/src/main/java/org/sopt/pingle/di/DataSourceModule.kt +++ b/app/src/main/java/org/sopt/pingle/di/DataSourceModule.kt @@ -11,12 +11,14 @@ import org.sopt.pingle.data.datasource.remote.AuthRemoteDataSource import org.sopt.pingle.data.datasource.remote.DummyRemoteDataSource import org.sopt.pingle.data.datasource.remote.MapRemoteDataSource import org.sopt.pingle.data.datasource.remote.PingleRemoteDataSource +import org.sopt.pingle.data.datasource.remote.PlanRemoteDataSource import org.sopt.pingle.data.datasourceimpl.local.DummyLocalDataSourceImpl import org.sopt.pingle.data.datasourceimpl.local.PingleLocalDataSourceImpl import org.sopt.pingle.data.datasourceimpl.remote.AuthRemoteDataSourceImpl import org.sopt.pingle.data.datasourceimpl.remote.DummyRemoteDataSourceImpl import org.sopt.pingle.data.datasourceimpl.remote.MapRemoteDataSourceImpl import org.sopt.pingle.data.datasourceimpl.remote.PingleRemoteDataSourceImpl +import org.sopt.pingle.data.datasourceimpl.remote.PlanRemoteDataSourceImpl @Module @InstallIn(SingletonComponent::class) @@ -44,4 +46,8 @@ abstract class DataSourceModule { @Binds @Singleton abstract fun bindsPingleLocalDataSource(pingleLocalDataSourceImpl: PingleLocalDataSourceImpl): PingleLocalDataSource + + @Binds + @Singleton + abstract fun bindsPlanRemoteDataSource(planRemoteDataSourceImpl: PlanRemoteDataSourceImpl): PlanRemoteDataSource } diff --git a/app/src/main/java/org/sopt/pingle/di/RepositoryModule.kt b/app/src/main/java/org/sopt/pingle/di/RepositoryModule.kt index a211f909..52c9d3a1 100644 --- a/app/src/main/java/org/sopt/pingle/di/RepositoryModule.kt +++ b/app/src/main/java/org/sopt/pingle/di/RepositoryModule.kt @@ -9,10 +9,12 @@ import org.sopt.pingle.data.repository.AuthRepositoryImpl import org.sopt.pingle.data.repository.DummyRepositoryImpl import org.sopt.pingle.data.repository.MapRepositoryImpl import org.sopt.pingle.data.repository.PingleRepositoryImpl +import org.sopt.pingle.data.repository.PlanRepositoryImpl import org.sopt.pingle.domain.repository.AuthRepository import org.sopt.pingle.domain.repository.DummyRepository import org.sopt.pingle.domain.repository.MapRepository import org.sopt.pingle.domain.repository.PingleRepository +import org.sopt.pingle.domain.repository.PlanRepository @Module @InstallIn(SingletonComponent::class) @@ -32,4 +34,8 @@ abstract class RepositoryModule { @Binds @Singleton abstract fun bindsPingleRepository(pingleRepositoryImpl: PingleRepositoryImpl): PingleRepository + + @Binds + @Singleton + abstract fun bindsPlanRepository(planRepositoryImpl: PlanRepositoryImpl): PlanRepository } diff --git a/app/src/main/java/org/sopt/pingle/di/ServiceModule.kt b/app/src/main/java/org/sopt/pingle/di/ServiceModule.kt index efff2c24..6c04eb0d 100644 --- a/app/src/main/java/org/sopt/pingle/di/ServiceModule.kt +++ b/app/src/main/java/org/sopt/pingle/di/ServiceModule.kt @@ -9,6 +9,7 @@ import org.sopt.pingle.data.service.AuthService import org.sopt.pingle.data.service.DummyService import org.sopt.pingle.data.service.MapService import org.sopt.pingle.data.service.PingleService +import org.sopt.pingle.data.service.PlanService import org.sopt.pingle.di.qualifier.Pingle import retrofit2.Retrofit import retrofit2.create @@ -35,4 +36,9 @@ object ServiceModule { @Singleton fun providesPingleService(@Pingle retrofit: Retrofit): PingleService = retrofit.create(PingleService::class.java) + + @Provides + @Singleton + fun providesPlanService(@Pingle retrofit: Retrofit): PlanService = + retrofit.create(PlanService::class.java) } diff --git a/app/src/main/java/org/sopt/pingle/di/UseCaseModule.kt b/app/src/main/java/org/sopt/pingle/di/UseCaseModule.kt index 3e94b15c..3056b06f 100644 --- a/app/src/main/java/org/sopt/pingle/di/UseCaseModule.kt +++ b/app/src/main/java/org/sopt/pingle/di/UseCaseModule.kt @@ -8,9 +8,11 @@ import javax.inject.Singleton import org.sopt.pingle.domain.repository.DummyRepository import org.sopt.pingle.domain.repository.MapRepository import org.sopt.pingle.domain.repository.PingleRepository +import org.sopt.pingle.domain.repository.PlanRepository import org.sopt.pingle.domain.usecase.GetDummyUserListUseCase import org.sopt.pingle.domain.usecase.GetPinListWithoutFilteringUseCase import org.sopt.pingle.domain.usecase.GetPingleListUseCase +import org.sopt.pingle.domain.usecase.GetPlanLocationListUseCase import org.sopt.pingle.domain.usecase.PostPingleCancelUseCase import org.sopt.pingle.domain.usecase.PostPingleJoinUseCase import org.sopt.pingle.domain.usecase.SetDummyDataUseCase @@ -47,4 +49,9 @@ class UseCaseModule { @Singleton fun providesPostPingleCancelUseCase(pingleRepository: PingleRepository): PostPingleCancelUseCase = PostPingleCancelUseCase(pingleRepository = pingleRepository) + + @Provides + @Singleton + fun providesGetPlanLocationListUseCase(planRepository: PlanRepository): GetPlanLocationListUseCase = + GetPlanLocationListUseCase(planRepository = planRepository) } diff --git a/app/src/main/java/org/sopt/pingle/domain/repository/PlanRepository.kt b/app/src/main/java/org/sopt/pingle/domain/repository/PlanRepository.kt new file mode 100644 index 00000000..bdb310db --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/domain/repository/PlanRepository.kt @@ -0,0 +1,8 @@ +package org.sopt.pingle.domain.repository + +import kotlinx.coroutines.flow.Flow +import org.sopt.pingle.domain.model.PlanLocationEntity + +interface PlanRepository { + suspend fun getPlanLocationList(searchWord: String): Flow> +} diff --git a/app/src/main/java/org/sopt/pingle/domain/usecase/GetPlanLocationListUseCase.kt b/app/src/main/java/org/sopt/pingle/domain/usecase/GetPlanLocationListUseCase.kt new file mode 100644 index 00000000..9075dd25 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/domain/usecase/GetPlanLocationListUseCase.kt @@ -0,0 +1,12 @@ +package org.sopt.pingle.domain.usecase + +import kotlinx.coroutines.flow.Flow +import org.sopt.pingle.domain.model.PlanLocationEntity +import org.sopt.pingle.domain.repository.PlanRepository + +class GetPlanLocationListUseCase( + private val planRepository: PlanRepository +) { + suspend operator fun invoke(searchWord: String): Flow> = + planRepository.getPlanLocationList(searchWord = searchWord) +} diff --git a/app/src/main/java/org/sopt/pingle/presentation/model/PlanLocationModel.kt b/app/src/main/java/org/sopt/pingle/presentation/model/PlanLocationModel.kt new file mode 100644 index 00000000..cf00f36c --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/presentation/model/PlanLocationModel.kt @@ -0,0 +1,9 @@ +package org.sopt.pingle.presentation.model + +import androidx.databinding.ObservableBoolean +import org.sopt.pingle.domain.model.PlanLocationEntity + +data class PlanLocationModel( + val planLocation: PlanLocationEntity, + var isSelected: ObservableBoolean = ObservableBoolean(false) +) diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanActivity.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanActivity.kt index eff9c241..2978d178 100644 --- a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanActivity.kt +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanActivity.kt @@ -7,6 +7,7 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope import androidx.viewpager2.widget.ViewPager2 +import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.sopt.pingle.R @@ -21,6 +22,7 @@ import org.sopt.pingle.presentation.ui.main.plan.plantitle.PlanTitleFragment import org.sopt.pingle.util.base.BindingActivity import org.sopt.pingle.util.component.AllModalDialogFragment +@AndroidEntryPoint class PlanActivity : BindingActivity(R.layout.activity_plan) { private val planViewModel: PlanViewModel by viewModels() private lateinit var fragmentList: ArrayList diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanViewModel.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanViewModel.kt index 96af2293..82fc42dd 100644 --- a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanViewModel.kt +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/PlanViewModel.kt @@ -2,18 +2,29 @@ package org.sopt.pingle.presentation.ui.main.plan import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject +import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch import org.sopt.pingle.domain.model.PlanLocationEntity +import org.sopt.pingle.domain.usecase.GetPlanLocationListUseCase import org.sopt.pingle.presentation.type.CategoryType import org.sopt.pingle.presentation.type.PlanType import org.sopt.pingle.util.combineAll +import org.sopt.pingle.util.view.UiState -class PlanViewModel : ViewModel() { +@HiltViewModel +class PlanViewModel @Inject constructor( + private val getPlanLocationListUseCase: GetPlanLocationListUseCase +) : ViewModel() { private val _currentPage = MutableStateFlow(FIRST_PAGE_POSITION) val currentPage get() = _currentPage.asStateFlow() val planTitle = MutableStateFlow("") @@ -29,15 +40,22 @@ class PlanViewModel : ViewModel() { val planOpenChattingLink = MutableStateFlow("") val planSummary = MutableStateFlow("") - private val _selectedLocation = MutableStateFlow(null) - val selectedLocation get() = _selectedLocation.asStateFlow() - private val _selectedCategory = MutableStateFlow(null) val selectedCategory get() = _selectedCategory.asStateFlow() private val _selectedRecruitment = MutableStateFlow("1") val selectedRecruitment get() = _selectedRecruitment.asStateFlow() + private val _planLocationListState = + MutableSharedFlow>>() + val planLocationListState get() = _planLocationListState.asSharedFlow() + + private val _planLocationList = MutableStateFlow>(emptyList()) + val planLocationList get() = _planLocationList.asStateFlow() + + private val _selectedLocation = MutableStateFlow(null) + val selectedLocation get() = _selectedLocation.asStateFlow() + val isPlanBtnEnabled: StateFlow = listOf( currentPage, selectedCategory, @@ -112,8 +130,29 @@ class PlanViewModel : ViewModel() { private var oldPosition = DEFAULT_OLD_POSITION - private val _planLocationList = MutableStateFlow>(emptyList()) - val planLocationList get() = _planLocationList.asStateFlow() + fun getPlanLocationList(searchWord: String) { + viewModelScope.launch { + _planLocationListState.emit(UiState.Loading) + _planLocationList.value = emptyList() + _selectedLocation.value = null + runCatching { + getPlanLocationListUseCase(searchWord).collect() { planLocationList -> + when (planLocationList.isEmpty()) { + true -> { + _planLocationListState.emit(UiState.Empty) + } + + false -> { + _planLocationList.value = planLocationList + _planLocationListState.emit(UiState.Success(planLocationList)) + } + } + } + }.onFailure { exception: Throwable -> + _planLocationListState.emit(UiState.Error(exception.message)) + } + } + } fun updatePlanLocationList(position: Int) { when (oldPosition) { @@ -131,63 +170,17 @@ class PlanViewModel : ViewModel() { setIsSelected(position) } } - _selectedLocation.value = if (getIsSelected(position)) _planLocationList.value[position] else null + _selectedLocation.value = + if (getIsSelected(position)) _planLocationList.value[position] else null oldPosition = position } - // 이전 값이 -> 초기값 + 셀렉티드 값이 있으면 - fun checkIsNull(): Boolean { - return _planLocationList.value.isEmpty() - // TODO return planLocationList.value.isEmpty() - } - private fun setIsSelected(position: Int) { _planLocationList.value[position].isSelected.set(!_planLocationList.value[position].isSelected.get()) } private fun getIsSelected(position: Int) = _planLocationList.value[position].isSelected.get() - init { - _planLocationList.value = listOf( - PlanLocationEntity( - location = "하얀집", - address = "서울 중구 퇴계로6길 12", - x = 123.5, - y = 56.7 - ), - PlanLocationEntity( - location = "하얀집2호점", - address = "서울 중구 퇴계로6길 12", - x = 123.5, - y = 56.7 - ), - PlanLocationEntity( - location = "하얀집3호점", - address = "서울 중구 퇴계로6길 12", - x = 123.5, - y = 56.7 - ), - PlanLocationEntity( - location = "하얀집 싫어싫어싫어", - address = "서울 중구 퇴계로6길 12", - x = 123.5, - y = 56.7 - ), - PlanLocationEntity( - location = "하얀집 좋아좋아좋아", - address = "서울 중구 퇴계로6길 12", - x = 123.5, - y = 56.7 - ), - PlanLocationEntity( - location = "하얀집웅시러", - address = "서울 중구 퇴계로6길 12", - x = 123.5, - y = 56.7 - ) - ) - } - companion object { const val FIRST_PAGE_POSITION = 0 const val DEFAULT_OLD_POSITION = -1 diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/plancategory/PlanCategoryFragment.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/plancategory/PlanCategoryFragment.kt index a5cb920c..97a3b7f7 100644 --- a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/plancategory/PlanCategoryFragment.kt +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/plancategory/PlanCategoryFragment.kt @@ -3,12 +3,14 @@ package org.sopt.pingle.presentation.ui.main.plan.plancategory import android.os.Bundle import android.view.View import androidx.fragment.app.activityViewModels +import dagger.hilt.android.AndroidEntryPoint import org.sopt.pingle.R import org.sopt.pingle.databinding.FragmentPlanCategoryBinding import org.sopt.pingle.presentation.type.CategoryType import org.sopt.pingle.presentation.ui.main.plan.PlanViewModel import org.sopt.pingle.util.base.BindingFragment +@AndroidEntryPoint class PlanCategoryFragment : BindingFragment(R.layout.fragment_plan_category) { private val viewModel by activityViewModels() diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/plandatetime/PlanDateTimeFragment.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/plandatetime/PlanDateTimeFragment.kt index 6a8971ca..7ea91916 100644 --- a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/plandatetime/PlanDateTimeFragment.kt +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/plandatetime/PlanDateTimeFragment.kt @@ -3,6 +3,7 @@ package org.sopt.pingle.presentation.ui.main.plan.plandatetime import android.os.Bundle import android.view.View import androidx.fragment.app.activityViewModels +import dagger.hilt.android.AndroidEntryPoint import java.text.SimpleDateFormat import java.time.LocalDate import java.util.Locale @@ -12,6 +13,7 @@ import org.sopt.pingle.presentation.ui.main.plan.PlanViewModel import org.sopt.pingle.util.base.BindingFragment import org.sopt.pingle.util.component.PingleSnackbar +@AndroidEntryPoint class PlanDateTimeFragment : BindingFragment(R.layout.fragment_plan_date_time) { private val planViewModel: PlanViewModel by activityViewModels() diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/planlocation/PlanLocationFragment.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/planlocation/PlanLocationFragment.kt index d16fa424..ab73d563 100644 --- a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/planlocation/PlanLocationFragment.kt +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/planlocation/PlanLocationFragment.kt @@ -4,13 +4,19 @@ import android.os.Bundle import android.view.KeyEvent import android.view.View import androidx.fragment.app.activityViewModels -import androidx.recyclerview.widget.LinearLayoutManager +import androidx.lifecycle.flowWithLifecycle +import androidx.lifecycle.lifecycleScope +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import org.sopt.pingle.R import org.sopt.pingle.databinding.FragmentPlanLocationBinding import org.sopt.pingle.presentation.ui.main.plan.PlanViewModel import org.sopt.pingle.util.base.BindingFragment import org.sopt.pingle.util.context.hideKeyboard +import org.sopt.pingle.util.view.UiState +@AndroidEntryPoint class PlanLocationFragment : BindingFragment(R.layout.fragment_plan_location) { private val planLocationViewModel by activityViewModels() @@ -23,29 +29,23 @@ class PlanLocationFragment : initLayout() addListeners() + collectData() } private fun initLayout() { - binding.rvPlanLocationList.apply { - this.layoutManager = LinearLayoutManager(context) - adapter = planLocationAdapter - /*addItemDecoration( - PlanLocationDivider(1, R.color.g_09), - )*/ - } - planLocationAdapter.submitList(planLocationViewModel.planLocationList.value) + binding.rvPlanLocationList.adapter = planLocationAdapter } private fun addListeners() { binding.ivPlanLocationSearchBtn.setOnClickListener { - checkListExist() + planLocationViewModel.getPlanLocationList(binding.etPlanLocationSearch.text.toString()) } val searchListener = binding.etPlanLocationSearch searchListener.setOnKeyListener( View.OnKeyListener { _, keyCode, event -> if (keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_UP) { - checkListExist() + planLocationViewModel.getPlanLocationList(binding.etPlanLocationSearch.text.toString()) requireActivity().hideKeyboard(searchListener) return@OnKeyListener true } @@ -54,20 +54,27 @@ class PlanLocationFragment : ) } - private fun deleteOldPosition(position: Int) { - planLocationViewModel.updatePlanLocationList(position) + private fun collectData() { + planLocationViewModel.planLocationListState.flowWithLifecycle(lifecycle).onEach { uiState -> + when (uiState) { + is UiState.Success -> { + planLocationAdapter.submitList(uiState.data) + planLocationAdapter.currentList + binding.layoutPlanLocationEmpty.visibility = View.INVISIBLE + } + + is UiState.Empty -> { + planLocationAdapter.submitList(null) + binding.layoutPlanLocationEmpty.visibility = View.VISIBLE + } + + else -> Unit + } + }.launchIn(lifecycleScope) } - private fun checkListExist() = if (planLocationViewModel.checkIsNull()) { - with(binding) { - rvPlanLocationList.visibility = View.INVISIBLE - layoutPlanLocationEmpty.visibility = View.VISIBLE - } - } else { - with(binding) { - rvPlanLocationList.visibility = View.VISIBLE - layoutPlanLocationEmpty.visibility = View.INVISIBLE - } + private fun deleteOldPosition(position: Int) { + planLocationViewModel.updatePlanLocationList(position) } override fun onDestroyView() { diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/planopenchatting/PlanOpenChattingFragment.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/planopenchatting/PlanOpenChattingFragment.kt index e310d001..cb865f37 100644 --- a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/planopenchatting/PlanOpenChattingFragment.kt +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/planopenchatting/PlanOpenChattingFragment.kt @@ -3,12 +3,14 @@ package org.sopt.pingle.presentation.ui.main.plan.planopenchatting import android.os.Bundle import android.view.View import androidx.fragment.app.activityViewModels +import dagger.hilt.android.AndroidEntryPoint import org.sopt.pingle.R import org.sopt.pingle.databinding.FragmentPlanOpenChattingBinding import org.sopt.pingle.presentation.ui.main.plan.PlanViewModel import org.sopt.pingle.util.base.BindingFragment import org.sopt.pingle.util.context.hideKeyboard +@AndroidEntryPoint class PlanOpenChattingFragment : BindingFragment(R.layout.fragment_plan_open_chatting) { private val planViewModel: PlanViewModel by activityViewModels() diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/planrecruitment/PlanRecruitmentFragment.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/planrecruitment/PlanRecruitmentFragment.kt index e6b80e01..781dac7d 100644 --- a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/planrecruitment/PlanRecruitmentFragment.kt +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/planrecruitment/PlanRecruitmentFragment.kt @@ -6,6 +6,7 @@ import android.view.View import androidx.fragment.app.activityViewModels import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope +import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.sopt.pingle.R @@ -14,6 +15,7 @@ import org.sopt.pingle.presentation.ui.main.plan.PlanViewModel import org.sopt.pingle.util.base.BindingFragment import org.sopt.pingle.util.context.hideKeyboard +@AndroidEntryPoint class PlanRecruitmentFragment : BindingFragment(R.layout.fragment_plan_recruitment) { diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/plansummaryconfirmation/PlanSummaryConfirmationFragment.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/plansummaryconfirmation/PlanSummaryConfirmationFragment.kt index 2d9f2ddb..488e9a1f 100644 --- a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/plansummaryconfirmation/PlanSummaryConfirmationFragment.kt +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/plansummaryconfirmation/PlanSummaryConfirmationFragment.kt @@ -3,12 +3,14 @@ package org.sopt.pingle.presentation.ui.main.plan.plansummaryconfirmation import android.os.Bundle import android.view.View import androidx.fragment.app.activityViewModels +import dagger.hilt.android.AndroidEntryPoint import org.sopt.pingle.R import org.sopt.pingle.databinding.FragmentPlanSummaryConfirmationBinding import org.sopt.pingle.presentation.ui.main.plan.PlanViewModel import org.sopt.pingle.util.base.BindingFragment import org.sopt.pingle.util.fragment.colorOf +@AndroidEntryPoint class PlanSummaryConfirmationFragment : BindingFragment(R.layout.fragment_plan_summary_confirmation) { private val viewModel by activityViewModels() diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/plantitle/PlanTitleFragment.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/plantitle/PlanTitleFragment.kt index 7d2092e6..dfa81f94 100644 --- a/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/plantitle/PlanTitleFragment.kt +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/main/plan/plantitle/PlanTitleFragment.kt @@ -3,12 +3,14 @@ package org.sopt.pingle.presentation.ui.main.plan.plantitle import android.os.Bundle import android.view.View import androidx.fragment.app.activityViewModels +import dagger.hilt.android.AndroidEntryPoint import org.sopt.pingle.R import org.sopt.pingle.databinding.FragmentPlanTitleBinding import org.sopt.pingle.presentation.ui.main.plan.PlanViewModel import org.sopt.pingle.util.base.BindingFragment import org.sopt.pingle.util.context.hideKeyboard +@AndroidEntryPoint class PlanTitleFragment : BindingFragment(R.layout.fragment_plan_title) { private val planViewModel: PlanViewModel by activityViewModels() override fun onViewCreated(view: View, savedInstanceState: Bundle?) {