From aa0096f48046cba9d4f9ef0b9005b6a75ba03a8d Mon Sep 17 00:00:00 2001 From: flash159483 Date: Fri, 4 Aug 2023 10:48:50 +0900 Subject: [PATCH] [LH-112] Connect api to view #16 --- .../android/data/api/BoardApiService.kt | 17 +++++++ .../lighthouse/android/data/model/BoardDTO.kt | 13 +++++ .../android/data/model/BoardQuestionDTO.kt | 26 ++++++++++ .../android/data/model/LanguageDTO.kt | 16 ++++++ .../data/repository/BoardRepositoryImpl.kt | 25 ++++++++++ .../datasource/BoardRemoteDataSource.kt | 9 ++++ .../BoardRemoteDataSourceImpl.kt | 21 ++++++++ .../domain/repository/BoardRepository.kt | 9 ++++ .../domain/response/vo/BoardQuestionVO.kt | 9 ++++ .../lighthouse/domain/response/vo/BoardVO.kt | 5 ++ .../domain/response/vo/LanguageVO.kt | 6 +++ .../domain/usecase/GetQuestionUseCase.kt | 11 +++++ .../board/viewmodel/BoardViewModel.kt | 49 +++++++++++++++++++ 13 files changed, 216 insertions(+) create mode 100644 data/src/main/java/com/lighthouse/android/data/api/BoardApiService.kt create mode 100644 data/src/main/java/com/lighthouse/android/data/model/BoardDTO.kt create mode 100644 data/src/main/java/com/lighthouse/android/data/model/BoardQuestionDTO.kt create mode 100644 data/src/main/java/com/lighthouse/android/data/model/LanguageDTO.kt create mode 100644 data/src/main/java/com/lighthouse/android/data/repository/BoardRepositoryImpl.kt create mode 100644 data/src/main/java/com/lighthouse/android/data/repository/datasource/BoardRemoteDataSource.kt create mode 100644 data/src/main/java/com/lighthouse/android/data/repository/datasourceimpl/BoardRemoteDataSourceImpl.kt create mode 100644 domain/src/main/java/com/lighthouse/domain/repository/BoardRepository.kt create mode 100644 domain/src/main/java/com/lighthouse/domain/response/vo/BoardQuestionVO.kt create mode 100644 domain/src/main/java/com/lighthouse/domain/response/vo/BoardVO.kt create mode 100644 domain/src/main/java/com/lighthouse/domain/response/vo/LanguageVO.kt create mode 100644 domain/src/main/java/com/lighthouse/domain/usecase/GetQuestionUseCase.kt create mode 100644 feature/board/src/main/java/com/lighthouse/board/viewmodel/BoardViewModel.kt diff --git a/data/src/main/java/com/lighthouse/android/data/api/BoardApiService.kt b/data/src/main/java/com/lighthouse/android/data/api/BoardApiService.kt new file mode 100644 index 00000000..f1ad2e13 --- /dev/null +++ b/data/src/main/java/com/lighthouse/android/data/api/BoardApiService.kt @@ -0,0 +1,17 @@ +package com.lighthouse.android.data.api + +import com.lighthouse.android.data.model.BaseResponse +import com.lighthouse.android.data.model.BoardDTO +import retrofit2.Response +import retrofit2.http.GET +import retrofit2.http.Path +import retrofit2.http.Query + +interface BoardApiService { + @GET("api/v1/question/[category]") + suspend fun getQuestion( + @Path("category") category: Int, + order: String, + @Query("page") page: Int, + ): Response> +} \ No newline at end of file diff --git a/data/src/main/java/com/lighthouse/android/data/model/BoardDTO.kt b/data/src/main/java/com/lighthouse/android/data/model/BoardDTO.kt new file mode 100644 index 00000000..b8a3c039 --- /dev/null +++ b/data/src/main/java/com/lighthouse/android/data/model/BoardDTO.kt @@ -0,0 +1,13 @@ +package com.lighthouse.android.data.model + +import com.google.gson.annotations.SerializedName +import com.lighthouse.domain.response.vo.BoardVO + +data class BoardDTO( + @SerializedName("questions") + val questions: List?, +) { + fun toVO() = BoardVO( + questions = questions?.map { it.toVO() } ?: listOf() + ) +} \ No newline at end of file diff --git a/data/src/main/java/com/lighthouse/android/data/model/BoardQuestionDTO.kt b/data/src/main/java/com/lighthouse/android/data/model/BoardQuestionDTO.kt new file mode 100644 index 00000000..dde75d6b --- /dev/null +++ b/data/src/main/java/com/lighthouse/android/data/model/BoardQuestionDTO.kt @@ -0,0 +1,26 @@ +package com.lighthouse.android.data.model + +import com.google.gson.annotations.SerializedName +import com.lighthouse.domain.response.vo.BoardQuestionVO + +data class BoardQuestionDTO( + @SerializedName("questionId") + val questionId: Int?, + @SerializedName("userId") + val userId: Int?, + @SerializedName("categoryId") + val categoryId: Int?, + @SerializedName("contents") + val contents: String?, + @SerializedName("like") + val like: Int?, +) { + fun toVO() = BoardQuestionVO( + questionId = questionId ?: -1, + userId = userId ?: -1, + categoryId = categoryId ?: -1, + contents = contents ?: " ", + like = like ?: -1 + ) + +} \ No newline at end of file diff --git a/data/src/main/java/com/lighthouse/android/data/model/LanguageDTO.kt b/data/src/main/java/com/lighthouse/android/data/model/LanguageDTO.kt new file mode 100644 index 00000000..f4c2c241 --- /dev/null +++ b/data/src/main/java/com/lighthouse/android/data/model/LanguageDTO.kt @@ -0,0 +1,16 @@ +package com.lighthouse.android.data.model + +import com.google.gson.annotations.SerializedName +import com.lighthouse.domain.response.vo.LanguageVO + +data class LanguageDTO( + @SerializedName("code") + val code: String?, + @SerializedName("level") + val level: Int?, +) { + fun toVO() = LanguageVO( + code ?: "kr", + level ?: -1 + ) +} \ No newline at end of file diff --git a/data/src/main/java/com/lighthouse/android/data/repository/BoardRepositoryImpl.kt b/data/src/main/java/com/lighthouse/android/data/repository/BoardRepositoryImpl.kt new file mode 100644 index 00000000..0f8272b9 --- /dev/null +++ b/data/src/main/java/com/lighthouse/android/data/repository/BoardRepositoryImpl.kt @@ -0,0 +1,25 @@ +package com.lighthouse.android.data.repository + +import com.lighthouse.android.data.repository.datasource.BoardRemoteDataSource +import com.lighthouse.domain.constriant.Resource +import com.lighthouse.domain.repository.BoardRepository +import com.lighthouse.domain.response.vo.BoardVO +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +import javax.inject.Inject + +class BoardRepositoryImpl @Inject constructor( + private val datasource: BoardRemoteDataSource, +) : BoardRepository { + override fun getBoardQuestions( + category: Int, + order: String, + page: Int, + ): Flow> = + datasource.getBoardQuestions(category, order, page).map { + when (it) { + is Resource.Success -> Resource.Success(it.data!!.toVO()) + else -> Resource.Error(it.message ?: "No message found") + } + } +} \ No newline at end of file diff --git a/data/src/main/java/com/lighthouse/android/data/repository/datasource/BoardRemoteDataSource.kt b/data/src/main/java/com/lighthouse/android/data/repository/datasource/BoardRemoteDataSource.kt new file mode 100644 index 00000000..ee051f61 --- /dev/null +++ b/data/src/main/java/com/lighthouse/android/data/repository/datasource/BoardRemoteDataSource.kt @@ -0,0 +1,9 @@ +package com.lighthouse.android.data.repository.datasource + +import com.lighthouse.android.data.model.BoardDTO +import com.lighthouse.domain.constriant.Resource +import kotlinx.coroutines.flow.Flow + +interface BoardRemoteDataSource { + fun getBoardQuestions(category: Int, order: String, page: Int): Flow> +} \ No newline at end of file diff --git a/data/src/main/java/com/lighthouse/android/data/repository/datasourceimpl/BoardRemoteDataSourceImpl.kt b/data/src/main/java/com/lighthouse/android/data/repository/datasourceimpl/BoardRemoteDataSourceImpl.kt new file mode 100644 index 00000000..aa2f3920 --- /dev/null +++ b/data/src/main/java/com/lighthouse/android/data/repository/datasourceimpl/BoardRemoteDataSourceImpl.kt @@ -0,0 +1,21 @@ +package com.lighthouse.android.data.repository.datasourceimpl + +import com.lighthouse.android.data.api.BoardApiService +import com.lighthouse.android.data.model.BoardDTO +import com.lighthouse.android.data.repository.datasource.BoardRemoteDataSource +import com.lighthouse.domain.constriant.Resource +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import javax.inject.Inject + +class BoardRemoteDataSourceImpl @Inject constructor( + private val api: BoardApiService, +) : BoardRemoteDataSource, NetworkResponse() { + override fun getBoardQuestions( + category: Int, + order: String, + page: Int, + ): Flow> = flow { + emit(changeResult(api.getQuestion(category, order, page))) + } +} \ No newline at end of file diff --git a/domain/src/main/java/com/lighthouse/domain/repository/BoardRepository.kt b/domain/src/main/java/com/lighthouse/domain/repository/BoardRepository.kt new file mode 100644 index 00000000..e1921014 --- /dev/null +++ b/domain/src/main/java/com/lighthouse/domain/repository/BoardRepository.kt @@ -0,0 +1,9 @@ +package com.lighthouse.domain.repository + +import com.lighthouse.domain.constriant.Resource +import com.lighthouse.domain.response.vo.BoardVO +import kotlinx.coroutines.flow.Flow + +interface BoardRepository { + fun getBoardQuestions(category: Int, order: String, page: Int): Flow> +} \ No newline at end of file diff --git a/domain/src/main/java/com/lighthouse/domain/response/vo/BoardQuestionVO.kt b/domain/src/main/java/com/lighthouse/domain/response/vo/BoardQuestionVO.kt new file mode 100644 index 00000000..e20d57f7 --- /dev/null +++ b/domain/src/main/java/com/lighthouse/domain/response/vo/BoardQuestionVO.kt @@ -0,0 +1,9 @@ +package com.lighthouse.domain.response.vo + +data class BoardQuestionVO( + val questionId: Int, + val userId: Int, + val categoryId: Int, + val contents: String, + val like: Int, +) \ No newline at end of file diff --git a/domain/src/main/java/com/lighthouse/domain/response/vo/BoardVO.kt b/domain/src/main/java/com/lighthouse/domain/response/vo/BoardVO.kt new file mode 100644 index 00000000..1d4efa54 --- /dev/null +++ b/domain/src/main/java/com/lighthouse/domain/response/vo/BoardVO.kt @@ -0,0 +1,5 @@ +package com.lighthouse.domain.response.vo + +data class BoardVO( + val questions: List, +) \ No newline at end of file diff --git a/domain/src/main/java/com/lighthouse/domain/response/vo/LanguageVO.kt b/domain/src/main/java/com/lighthouse/domain/response/vo/LanguageVO.kt new file mode 100644 index 00000000..3fdd1c63 --- /dev/null +++ b/domain/src/main/java/com/lighthouse/domain/response/vo/LanguageVO.kt @@ -0,0 +1,6 @@ +package com.lighthouse.domain.response.vo + +data class LanguageVO( + val code: String, + val level: Int, +) \ No newline at end of file diff --git a/domain/src/main/java/com/lighthouse/domain/usecase/GetQuestionUseCase.kt b/domain/src/main/java/com/lighthouse/domain/usecase/GetQuestionUseCase.kt new file mode 100644 index 00000000..00fa3fff --- /dev/null +++ b/domain/src/main/java/com/lighthouse/domain/usecase/GetQuestionUseCase.kt @@ -0,0 +1,11 @@ +package com.lighthouse.domain.usecase + +import com.lighthouse.domain.repository.BoardRepository +import javax.inject.Inject + +class GetQuestionUseCase @Inject constructor( + private val repository: BoardRepository, +) { + fun invoke(category: Int, order: String, page: Int) = + repository.getBoardQuestions(category, order, page) +} \ No newline at end of file diff --git a/feature/board/src/main/java/com/lighthouse/board/viewmodel/BoardViewModel.kt b/feature/board/src/main/java/com/lighthouse/board/viewmodel/BoardViewModel.kt new file mode 100644 index 00000000..8235c453 --- /dev/null +++ b/feature/board/src/main/java/com/lighthouse/board/viewmodel/BoardViewModel.kt @@ -0,0 +1,49 @@ +package com.lighthouse.board.viewmodel + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.lighthouse.board.util.UiState +import com.lighthouse.domain.constriant.Resource +import com.lighthouse.domain.usecase.GetQuestionUseCase +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn +import javax.inject.Inject + +class BoardViewModel @Inject constructor( + private val getQuestionUseCase: GetQuestionUseCase, +) : ViewModel() { + private var cachedState: StateFlow? = null + val category = MutableLiveData() + val order = MutableLiveData() + + val state: Flow + get() { + if (cachedState == null) { + cachedState = fetchState() + } + return cachedState!! + } + + private fun fetchState(): StateFlow { + return getQuestionUseCase.invoke(category.value!!, order.value!!, 1) + .map { + when (it) { + is Resource.Success -> UiState.Success(it.data!!.questions) + is Resource.Error -> UiState.Error(it.message ?: "Error found") + } + } + .catch { + emit(UiState.Error(it.message ?: "Error found")) + } + .stateIn( + scope = viewModelScope, + initialValue = UiState.Loading, + started = SharingStarted.WhileSubscribed(5000) + ) + } +} \ No newline at end of file