Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] 마이페이지 북마크한 빵집 모아보기 api 연동 #47

Merged
merged 8 commits into from
Jul 19, 2023
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.sopt.geonppang.data.datasource.remote

import com.sopt.geonppang.data.model.response.ResponseMypageBookmark
import com.sopt.geonppang.data.model.response.ResponseMypageReview
import com.sopt.geonppang.data.service.MypageService
import javax.inject.Inject

class MypageDataSource @Inject constructor(
private val mypageService: MypageService,
) {
suspend fun fetchMyBookmarkList(): ResponseMypageBookmark =
mypageService.fetchMypageBookmark()

suspend fun fetchMyReviewList(): ResponseMypageReview =
mypageService.fethcMypageReveiw()
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.sopt.geonppang.data.model.response

import com.sopt.geonppang.domain.model.Bakery
import com.sopt.geonppang.domain.model.BreadType
import kotlinx.serialization.Serializable

@Serializable
data class ResponseMypageBookmark(
val code: Int,
val message: String,
val data: List<Data>
) {
@Serializable
data class Data(
val bakeryId: Int,
val bakeryName: String,
val bakeryPicture: String,
val isHACCP: Boolean,
val isVegan: Boolean,
val isNonGMO: Boolean,
val firstNearStation: String,
val secondNearStation: String,
val isBookMarked: Boolean,
val bookMarkCount: Int,
val reviewCount: Int,
val breadType: BreadType
) {
@Serializable
data class BreadType(
val breadTypeId: Int,
val breadTypeName: String,
val isGlutenFree: Boolean,
val isVegan: Boolean,
val isNutFree: Boolean,
val isSugarFree: Boolean,
)
}

fun toMypageBookmark() = data.map { myBookmark ->
Bakery(
bakeryId = myBookmark.bakeryId,
bakeryName = myBookmark.bakeryName,
bakeryPicture = myBookmark.bakeryPicture,
bookmarkCount = myBookmark.bookMarkCount,
firstNearStation = myBookmark.firstNearStation,
secondNearStation = myBookmark.secondNearStation,
isNonGMO = myBookmark.isNonGMO,
isVegan = myBookmark.isVegan,
isHACCP = myBookmark.isHACCP,
breadType = BreadType(
myBookmark.breadType.breadTypeId,
myBookmark.breadType.breadTypeName,
myBookmark.breadType.isGlutenFree,
myBookmark.breadType.isVegan,
myBookmark.breadType.isNutFree,
myBookmark.breadType.isSugarFree,
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.sopt.geonppang.data.repository

import com.sopt.geonppang.data.datasource.remote.MypageDataSource
import com.sopt.geonppang.domain.model.Bakery
import com.sopt.geonppang.domain.model.MyReview
import com.sopt.geonppang.domain.repository.MypageRepository
import javax.inject.Inject

class MypageRepositoryImpl @Inject constructor(
private val mypageDataSource: MypageDataSource,
) : MypageRepository {
override suspend fun fetchMyBookmark(): Result<List<Bakery>> = runCatching {
mypageDataSource.fetchMyBookmarkList().toMypageBookmark()
}

override suspend fun fetchMyReview(): Result<List<MyReview>> = runCatching {
mypageDataSource.fetchMyReviewList().toMyReview()
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package com.sopt.geonppang.data.service

import com.sopt.geonppang.data.model.response.ResponseMypageBookmark
import com.sopt.geonppang.data.model.response.ResponseMypageReview
import retrofit2.http.GET

interface MypageReviewService {
interface MypageService {
@GET("member/bookMarks")
suspend fun fetchMypageBookmark(): ResponseMypageBookmark

@GET("member/reviews")
suspend fun fethcMypageReveiw(): ResponseMypageReview
}
10 changes: 5 additions & 5 deletions app/src/main/java/com/sopt/geonppang/di/RepositoryModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ package com.sopt.geonppang.di

import com.sopt.geonppang.data.repository.BakeryRepositoryImpl
import com.sopt.geonppang.data.repository.DummyRepositoryImpl
import com.sopt.geonppang.data.repository.MypageReviewRepositoryImpl
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.DummyRepository
import com.sopt.geonppang.domain.repository.HomeRepository
import com.sopt.geonppang.domain.repository.MypageReviewRepository
import com.sopt.geonppang.domain.repository.MypageRepository
import com.sopt.geonppang.domain.repository.SearchRepository
import dagger.Binds
import dagger.Module
Expand Down Expand Up @@ -45,7 +45,7 @@ interface RepositoryModule {

@Binds
@Singleton
fun bindMypageReviewRepository(
mypageReviewRepositoryImpl: MypageReviewRepositoryImpl,
): MypageReviewRepository
fun bindMypageRepository(
mypageRepositoryImpl: MypageRepositoryImpl,
): MypageRepository
}
7 changes: 3 additions & 4 deletions app/src/main/java/com/sopt/geonppang/di/ServiceModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ package com.sopt.geonppang.di
import com.sopt.geonppang.data.service.BakeryService
import com.sopt.geonppang.data.service.DummyService
import com.sopt.geonppang.data.service.HomeService
import com.sopt.geonppang.data.service.MypageService
import com.sopt.geonppang.data.service.SearchService
import com.sopt.geonppang.data.service.MypageReviewService
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import retrofit2.Retrofit
import retrofit2.create
import javax.inject.Singleton

@Module
Expand Down Expand Up @@ -38,6 +37,6 @@ object ServiceModule {

@Singleton
@Provides
fun provideMypageReviewInfoService(retrofit: Retrofit): MypageReviewService =
retrofit.create(MypageReviewService::class.java)
fun provideMypageService(retrofit: Retrofit): MypageService =
retrofit.create(MypageService::class.java)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.sopt.geonppang.domain.repository

import com.sopt.geonppang.domain.model.Bakery
import com.sopt.geonppang.domain.model.MyReview

interface MypageReviewRepository {
interface MypageRepository {
suspend fun fetchMyBookmark(): Result<List<Bakery>>
suspend fun fetchMyReview(): Result<List<MyReview>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import androidx.fragment.app.viewModels
import com.sopt.geonppang.R
import com.sopt.geonppang.databinding.FragmentMyPageBinding
import com.sopt.geonppang.util.binding.BindingFragment
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class MyPageFragment : BindingFragment<FragmentMyPageBinding>(R.layout.fragment_my_page) {
private val viewModel by viewModels<MyPageViewModel>()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ import com.sopt.geonppang.domain.model.Bakery
import com.sopt.geonppang.domain.model.BreadType
import com.sopt.geonppang.domain.model.MyReview
import com.sopt.geonppang.domain.model.Profile
import com.sopt.geonppang.domain.repository.MypageReviewRepository
import com.sopt.geonppang.domain.repository.MypageRepository
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 timber.log.Timber
import javax.inject.Inject

@HiltViewModel
class MyPageViewModel @Inject constructor(
private val mypageReviewRepository: MypageReviewRepository,
private val mypageRepository: MypageRepository,
) : ViewModel() {
private val _profile = Profile(
memberNickname = "안빵이들",
Expand All @@ -38,81 +39,37 @@ class MyPageViewModel @Inject constructor(
private var _myReviewCount = MutableStateFlow<Int?>(null)
val myReviewCount get() = _myReviewCount.asStateFlow()

private var _mypageBookmarkListState = MutableStateFlow<UiState<List<Bakery>>>(UiState.Loading)
val mypageBookmarkListState get() = _mypageBookmarkListState.asStateFlow()

private var _myBookmarkCount = MutableStateFlow<Int?>(null)
val myBookmarkCount get() = _myBookmarkCount.asStateFlow()

init {
fetchMypageReviewList()
fetchMypageBookmarkList()
}

private fun fetchMypageReviewList() {
viewModelScope.launch {
mypageReviewRepository.fetchMyReview()
.onSuccess { myReviewList ->
_mypageReviewListState.value = UiState.Success(myReviewList)
_myReviewCount.value = myReviewList.size
}
.onFailure { throwable ->
_mypageReviewListState.value = UiState.Error(throwable.message)
}
mypageRepository.fetchMyReview().onSuccess { myReviewList ->
_mypageReviewListState.value = UiState.Success(myReviewList)
_myReviewCount.value = myReviewList.size
}.onFailure { throwable ->
_mypageReviewListState.value = UiState.Error(throwable.message)
}
}
}

// 마이페이지 북마크 더미데이터
val mockStoreList = listOf(
Bakery(
bakeryId = 1,
bakeryName = "건대 비건빵아아아아아아아아아",
firstNearStation = "건대역",
secondNearStation = null,
bookmarkCount = 5,
bakeryPicture = "https://search.pstatic.net/common/?src=https%3A%2F%2Fldb-phinf.pstatic.net%2F20220526_91%2F1653554529250qdOYp_JPEG%2F0E35EAC3-F936-41C7-BEE4-645B83AED8B1.jpeg",
isHACCP = true,
isNonGMO = true,
isVegan = true,
breadType = BreadType(
breadTypeId = 1,
breadTypeName = "글루텐프리",
isGlutenFree = true,
isVegan = true,
isNutFree = true,
isSugarFree = true,
)
),
Bakery(
bakeryId = 2,
bakeryName = "건대 비건빵아아아아아아",
firstNearStation = "덕소역",
secondNearStation = "구리역",
bookmarkCount = 7,
bakeryPicture = "https://search.pstatic.net/common/?src=https%3A%2F%2Fldb-phinf.pstatic.net%2F20220526_91%2F1653554529250qdOYp_JPEG%2F0E35EAC3-F936-41C7-BEE4-645B83AED8B1.jpeg",
isHACCP = false,
isNonGMO = true,
isVegan = true,
breadType = BreadType(
breadTypeId = 2,
breadTypeName = "글루텐프리",
isGlutenFree = false,
isVegan = true,
isNutFree = true,
isSugarFree = true,
)
),
Bakery(
bakeryId = 3,
bakeryName = "건대 비건빵아아아아아아",
firstNearStation = "덕소역",
secondNearStation = "구리역",
bookmarkCount = 0,
bakeryPicture = "https://search.pstatic.net/common/?src=https%3A%2F%2Fldb-phinf.pstatic.net%2F20220526_91%2F1653554529250qdOYp_JPEG%2F0E35EAC3-F936-41C7-BEE4-645B83AED8B1.jpeg",
isHACCP = false,
isNonGMO = true,
isVegan = false,
breadType = BreadType(
breadTypeId = 3,
breadTypeName = "글루텐프리",
isGlutenFree = true,
isVegan = true,
isNutFree = true,
isSugarFree = false,
)
),
)
private fun fetchMypageBookmarkList() {
viewModelScope.launch {
mypageRepository.fetchMyBookmark().onSuccess { myBookmarkList ->
_mypageBookmarkListState.value = UiState.Success(myBookmarkList)
_myBookmarkCount.value = myBookmarkList.size
Timber.e(_myBookmarkCount.value.toString())
}.onFailure { throwable ->
_mypageBookmarkListState.value = UiState.Error(throwable.message)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,57 @@ package com.sopt.geonppang.presentation.mypage

import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import com.sopt.geonppang.R
import com.sopt.geonppang.databinding.ActivityMyStoreListBinding
import com.sopt.geonppang.presentation.search.BakeryAdapter
import com.sopt.geonppang.util.UiState
import com.sopt.geonppang.util.binding.BindingActivity
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import timber.log.Timber

@AndroidEntryPoint
class MyStoreListActivity :
BindingActivity<ActivityMyStoreListBinding>(R.layout.activity_my_store_list) {
private val myPageViewModel: MyPageViewModel by viewModels()
lateinit var bakeryAdapter: BakeryAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding.viewModel = myPageViewModel
binding.lifecycleOwner = this

initLayout()
addListeners()
collectData()
}

private fun initLayout() {
bakeryAdapter = BakeryAdapter()
binding.rvStoreList.adapter = bakeryAdapter
bakeryAdapter.submitList(myPageViewModel.mockStoreList)
}

private fun addListeners() {
binding.toolbar.ivBack.setOnClickListener {
finish()
}
}

private fun collectData() {
myPageViewModel.mypageBookmarkListState.flowWithLifecycle(lifecycle).onEach {
when (it) {
is UiState.Success -> {
bakeryAdapter.submitList(it.data)
}

is UiState.Error -> {
Timber.e(it.message)
}

else -> {}
}
}.launchIn(lifecycleScope)
}
}
Loading
Loading