From 070b88679aa4c629b9d659aeb905c04d61ffa08e Mon Sep 17 00:00:00 2001 From: Sangho Kim Date: Fri, 12 Jul 2024 16:03:53 +0900 Subject: [PATCH 1/6] =?UTF-8?q?[ADD/#42]=20=EC=83=81=ED=92=88=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20API=20domain=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/co/orange/ddanzi/di/ServiceModule.kt | 1 - .../domain/entity/response/OptionModel.kt | 3 +- .../domain/repository/DetailRepository.kt | 7 ++ .../presentation/detail/DetailActivity.kt | 2 +- .../presentation/detail/DetailViewModel.kt | 75 ++++++++++--------- 5 files changed, 50 insertions(+), 38 deletions(-) create mode 100644 domain/src/main/kotlin/co/orange/domain/repository/DetailRepository.kt diff --git a/app/src/main/java/co/orange/ddanzi/di/ServiceModule.kt b/app/src/main/java/co/orange/ddanzi/di/ServiceModule.kt index 7d6bd679..8942fb7e 100644 --- a/app/src/main/java/co/orange/ddanzi/di/ServiceModule.kt +++ b/app/src/main/java/co/orange/ddanzi/di/ServiceModule.kt @@ -18,7 +18,6 @@ object ServiceModule { @RetrofitQualifier.NOTOKEN retrofit: Retrofit, ): AuthService = retrofit.create(AuthService::class.java) - // TODO 추후 수정 @Provides @Singleton fun provideHomeService( diff --git a/domain/src/main/kotlin/co/orange/domain/entity/response/OptionModel.kt b/domain/src/main/kotlin/co/orange/domain/entity/response/OptionModel.kt index 05bb0bb5..f0c125a5 100644 --- a/domain/src/main/kotlin/co/orange/domain/entity/response/OptionModel.kt +++ b/domain/src/main/kotlin/co/orange/domain/entity/response/OptionModel.kt @@ -8,5 +8,6 @@ data class OptionModel( data class OptionDetailModel( val optionDetailId: Long, val content: String, + val isAvailable: Boolean, ) -} \ No newline at end of file +} diff --git a/domain/src/main/kotlin/co/orange/domain/repository/DetailRepository.kt b/domain/src/main/kotlin/co/orange/domain/repository/DetailRepository.kt new file mode 100644 index 00000000..424e7a73 --- /dev/null +++ b/domain/src/main/kotlin/co/orange/domain/repository/DetailRepository.kt @@ -0,0 +1,7 @@ +package co.orange.domain.repository + +import co.orange.domain.entity.response.ProductDetailModel + +interface DetailRepository { + suspend fun getProductDetail(id: String): Result +} diff --git a/presentation/src/main/java/co/orange/presentation/detail/DetailActivity.kt b/presentation/src/main/java/co/orange/presentation/detail/DetailActivity.kt index be68f3c5..cc5141c8 100644 --- a/presentation/src/main/java/co/orange/presentation/detail/DetailActivity.kt +++ b/presentation/src/main/java/co/orange/presentation/detail/DetailActivity.kt @@ -62,7 +62,7 @@ class DetailActivity : BaseActivity(R.layout.activity_det private fun getIntentInfo() { with(viewModel) { - productId = intent.getLongExtra(EXTRA_PRODUCT_ID, -1) + productId = intent.getStringExtra(EXTRA_PRODUCT_ID).orEmpty() imageUrl = intent.getStringExtra(EXTRA_PRODUCT_URL).orEmpty() originPrice = intent.getIntExtra(EXTRA_ORIGIN_PRICE, 0) salePrice = intent.getIntExtra(EXTRA_SALE_PRICE, 0) diff --git a/presentation/src/main/java/co/orange/presentation/detail/DetailViewModel.kt b/presentation/src/main/java/co/orange/presentation/detail/DetailViewModel.kt index 3016d55d..1f347e0b 100644 --- a/presentation/src/main/java/co/orange/presentation/detail/DetailViewModel.kt +++ b/presentation/src/main/java/co/orange/presentation/detail/DetailViewModel.kt @@ -8,39 +8,44 @@ import javax.inject.Inject @HiltViewModel class DetailViewModel -@Inject -constructor( - // private val feedRepository: FeedRepository, -) : ViewModel() { - var productId: Long = -1 - var imageUrl: String = "" - var originPrice: Int = 0 - var salePrice: Int = 0 + @Inject + constructor( + // private val feedRepository: FeedRepository, + ) : ViewModel() { + var productId: String = "" + var imageUrl: String = "" + var originPrice: Int = 0 + var salePrice: Int = 0 - val mockProduct = ProductDetailModel( - "퓨어 오일 퍼퓸 10 ml 긴제목테스트트트트트", - "카테고리", - false, - true, - 30, - 12, - "", - 123, - listOf( - OptionModel( - 1, "색상", listOf( - OptionModel.OptionDetailModel(0, "네이비"), - OptionModel.OptionDetailModel(1, "블랙"), - ) - ), - OptionModel( - 2, "사이즈", listOf( - OptionModel.OptionDetailModel(0, "S"), - OptionModel.OptionDetailModel(1, "M"), - OptionModel.OptionDetailModel(2, "L"), - OptionModel.OptionDetailModel(3, "XL"), - ) - ), - ) - ) -} \ No newline at end of file + val mockProduct = + ProductDetailModel( + "퓨어 오일 퍼퓸 10 ml 긴제목테스트트트트트", + "카테고리", + false, + true, + 30, + 12, + "", + 123, + listOf( + OptionModel( + 1, + "색상", + listOf( + OptionModel.OptionDetailModel(0, "네이비", true), + OptionModel.OptionDetailModel(1, "블랙", true), + ), + ), + OptionModel( + 2, + "사이즈", + listOf( + OptionModel.OptionDetailModel(0, "S", true), + OptionModel.OptionDetailModel(1, "M", true), + OptionModel.OptionDetailModel(2, "L", true), + OptionModel.OptionDetailModel(3, "XL", true), + ), + ), + ), + ) + } From 9eb10aaa5f56768a63fcf9dc9699edcbc7f94030 Mon Sep 17 00:00:00 2001 From: Sangho Kim Date: Fri, 12 Jul 2024 16:09:16 +0900 Subject: [PATCH 2/6] =?UTF-8?q?[ADD/#42]=20=EC=83=81=ED=92=88=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20API=20dto,=20model=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/dto/response/ProductDetailDto.kt | 40 +++++++++++++++++++ .../data/dto/response/ProductOptionDto.kt | 29 ++++++++++++++ .../entity/response/ProductDetailModel.kt | 4 +- .../{OptionModel.kt => ProductOptionModel.kt} | 2 +- .../presentation/detail/DetailViewModel.kt | 18 ++++----- .../presentation/detail/OptionAdapter.kt | 8 ++-- .../detail/OptionDetailAdapter.kt | 2 +- .../detail/OptionDetailViewHolder.kt | 14 ++++--- .../presentation/detail/OptionViewHolder.kt | 22 +++++----- 9 files changed, 106 insertions(+), 33 deletions(-) create mode 100644 data/src/main/java/co/orange/data/dto/response/ProductDetailDto.kt create mode 100644 data/src/main/java/co/orange/data/dto/response/ProductOptionDto.kt rename domain/src/main/kotlin/co/orange/domain/entity/response/{OptionModel.kt => ProductOptionModel.kt} (90%) diff --git a/data/src/main/java/co/orange/data/dto/response/ProductDetailDto.kt b/data/src/main/java/co/orange/data/dto/response/ProductDetailDto.kt new file mode 100644 index 00000000..6e99c4e7 --- /dev/null +++ b/data/src/main/java/co/orange/data/dto/response/ProductDetailDto.kt @@ -0,0 +1,40 @@ +package co.orange.data.dto.response + +import co.orange.domain.entity.response.ProductDetailModel +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class ProductDetailDto( + @SerialName("name") + val name: String, + @SerialName("category") + val category: String, + @SerialName("isOptionExist") + val isOptionExist: Boolean, + @SerialName("isImminent") + val isImminent: Boolean, + @SerialName("discountRate") + val discountRate: Int, + @SerialName("stockCount") + val stockCount: Int, + @SerialName("infoUrl") + val infoUrl: String, + @SerialName("interestCount") + val interestCount: Int, + @SerialName("optionList") + val optionList: List, +) { + fun toModel() = + ProductDetailModel( + name, + category, + isOptionExist, + isImminent, + discountRate, + stockCount, + infoUrl, + interestCount, + optionList.map { it.toModel() }, + ) +} diff --git a/data/src/main/java/co/orange/data/dto/response/ProductOptionDto.kt b/data/src/main/java/co/orange/data/dto/response/ProductOptionDto.kt new file mode 100644 index 00000000..c38f46c3 --- /dev/null +++ b/data/src/main/java/co/orange/data/dto/response/ProductOptionDto.kt @@ -0,0 +1,29 @@ +package co.orange.data.dto.response + +import co.orange.domain.entity.response.ProductOptionModel +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class ProductOptionDto( + @SerialName("optionId") + val optionId: Long, + @SerialName("type") + val type: String, + @SerialName("optionDetailList") + val optionDetailList: List, +) { + @Serializable + data class OptionDetailDto( + @SerialName("optionDetailId") + val optionDetailId: Long, + @SerialName("content") + val content: String, + @SerialName("isAvailable") + val isAvailable: Boolean, + ) { + fun toModel() = ProductOptionModel.OptionDetailModel(optionDetailId, content, isAvailable) + } + + fun toModel() = ProductOptionModel(optionId, type, optionDetailList.map { it.toModel() }) +} diff --git a/domain/src/main/kotlin/co/orange/domain/entity/response/ProductDetailModel.kt b/domain/src/main/kotlin/co/orange/domain/entity/response/ProductDetailModel.kt index 5dab9af7..516752ce 100644 --- a/domain/src/main/kotlin/co/orange/domain/entity/response/ProductDetailModel.kt +++ b/domain/src/main/kotlin/co/orange/domain/entity/response/ProductDetailModel.kt @@ -9,5 +9,5 @@ data class ProductDetailModel( val stockCount: Int, val infoUrl: String, val interestCount: Int, - val optionList: List -) \ No newline at end of file + val optionList: List, +) diff --git a/domain/src/main/kotlin/co/orange/domain/entity/response/OptionModel.kt b/domain/src/main/kotlin/co/orange/domain/entity/response/ProductOptionModel.kt similarity index 90% rename from domain/src/main/kotlin/co/orange/domain/entity/response/OptionModel.kt rename to domain/src/main/kotlin/co/orange/domain/entity/response/ProductOptionModel.kt index f0c125a5..281d485b 100644 --- a/domain/src/main/kotlin/co/orange/domain/entity/response/OptionModel.kt +++ b/domain/src/main/kotlin/co/orange/domain/entity/response/ProductOptionModel.kt @@ -1,6 +1,6 @@ package co.orange.domain.entity.response -data class OptionModel( +data class ProductOptionModel( val optionId: Long, val type: String, val optionDetailList: List, diff --git a/presentation/src/main/java/co/orange/presentation/detail/DetailViewModel.kt b/presentation/src/main/java/co/orange/presentation/detail/DetailViewModel.kt index 1f347e0b..751345a0 100644 --- a/presentation/src/main/java/co/orange/presentation/detail/DetailViewModel.kt +++ b/presentation/src/main/java/co/orange/presentation/detail/DetailViewModel.kt @@ -1,8 +1,8 @@ package co.orange.presentation.detail import androidx.lifecycle.ViewModel -import co.orange.domain.entity.response.OptionModel import co.orange.domain.entity.response.ProductDetailModel +import co.orange.domain.entity.response.ProductOptionModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @@ -28,22 +28,22 @@ class DetailViewModel "", 123, listOf( - OptionModel( + ProductOptionModel( 1, "색상", listOf( - OptionModel.OptionDetailModel(0, "네이비", true), - OptionModel.OptionDetailModel(1, "블랙", true), + ProductOptionModel.OptionDetailModel(0, "네이비", true), + ProductOptionModel.OptionDetailModel(1, "블랙", true), ), ), - OptionModel( + ProductOptionModel( 2, "사이즈", listOf( - OptionModel.OptionDetailModel(0, "S", true), - OptionModel.OptionDetailModel(1, "M", true), - OptionModel.OptionDetailModel(2, "L", true), - OptionModel.OptionDetailModel(3, "XL", true), + ProductOptionModel.OptionDetailModel(0, "S", true), + ProductOptionModel.OptionDetailModel(1, "M", true), + ProductOptionModel.OptionDetailModel(2, "L", true), + ProductOptionModel.OptionDetailModel(3, "XL", true), ), ), ), diff --git a/presentation/src/main/java/co/orange/presentation/detail/OptionAdapter.kt b/presentation/src/main/java/co/orange/presentation/detail/OptionAdapter.kt index d142eb19..f2cfcaac 100644 --- a/presentation/src/main/java/co/orange/presentation/detail/OptionAdapter.kt +++ b/presentation/src/main/java/co/orange/presentation/detail/OptionAdapter.kt @@ -4,12 +4,12 @@ import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.ListAdapter import co.orange.core.util.ItemDiffCallback -import co.orange.domain.entity.response.OptionModel +import co.orange.domain.entity.response.ProductOptionModel import kr.genti.presentation.databinding.ItemOptionBinding class OptionAdapter( private val itemClick: (Int, Long, Long) -> Unit, -) : ListAdapter(diffUtil) { +) : ListAdapter(diffUtil) { override fun onCreateViewHolder( parent: ViewGroup, viewType: Int, @@ -28,7 +28,7 @@ class OptionAdapter( holder.onBind(item, position) } - fun addList(newItems: List) { + fun addList(newItems: List) { val currentItems = currentList.toMutableList() currentItems.addAll(newItems) submitList(currentItems) @@ -36,7 +36,7 @@ class OptionAdapter( companion object { private val diffUtil = - ItemDiffCallback( + ItemDiffCallback( onItemsTheSame = { old, new -> old.optionId == new.optionId }, onContentsTheSame = { old, new -> old == new }, ) diff --git a/presentation/src/main/java/co/orange/presentation/detail/OptionDetailAdapter.kt b/presentation/src/main/java/co/orange/presentation/detail/OptionDetailAdapter.kt index 3b96dfc6..f7efde71 100644 --- a/presentation/src/main/java/co/orange/presentation/detail/OptionDetailAdapter.kt +++ b/presentation/src/main/java/co/orange/presentation/detail/OptionDetailAdapter.kt @@ -5,7 +5,7 @@ import android.view.ViewGroup import androidx.recyclerview.widget.ListAdapter import co.orange.core.extension.setOnSingleClickListener import co.orange.core.util.ItemDiffCallback -import co.orange.domain.entity.response.OptionModel.OptionDetailModel +import co.orange.domain.entity.response.ProductOptionModel.OptionDetailModel import kr.genti.presentation.databinding.ItemOptionDetailBinding class OptionDetailAdapter( diff --git a/presentation/src/main/java/co/orange/presentation/detail/OptionDetailViewHolder.kt b/presentation/src/main/java/co/orange/presentation/detail/OptionDetailViewHolder.kt index 2f277c11..6cb2a7ed 100644 --- a/presentation/src/main/java/co/orange/presentation/detail/OptionDetailViewHolder.kt +++ b/presentation/src/main/java/co/orange/presentation/detail/OptionDetailViewHolder.kt @@ -2,23 +2,25 @@ package co.orange.presentation.detail import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView -import co.orange.domain.entity.response.OptionModel.OptionDetailModel +import co.orange.domain.entity.response.ProductOptionModel.OptionDetailModel import kr.genti.presentation.R import kr.genti.presentation.databinding.ItemOptionDetailBinding class OptionDetailViewHolder( - val binding: ItemOptionDetailBinding + val binding: ItemOptionDetailBinding, ) : RecyclerView.ViewHolder(binding.root) { - var isSelected = false fun onBind(item: OptionDetailModel) { with(binding) { tvOptionItemDetailTitle.text = item.content tvOptionItemDetailTitle.setTextColor( - if (isSelected) ContextCompat.getColor(itemView.context, R.color.black) - else ContextCompat.getColor(itemView.context, R.color.gray_2) + if (isSelected) { + ContextCompat.getColor(itemView.context, R.color.black) + } else { + ContextCompat.getColor(itemView.context, R.color.gray_2) + }, ) } } -} \ No newline at end of file +} diff --git a/presentation/src/main/java/co/orange/presentation/detail/OptionViewHolder.kt b/presentation/src/main/java/co/orange/presentation/detail/OptionViewHolder.kt index 966ef970..21180039 100644 --- a/presentation/src/main/java/co/orange/presentation/detail/OptionViewHolder.kt +++ b/presentation/src/main/java/co/orange/presentation/detail/OptionViewHolder.kt @@ -2,18 +2,20 @@ package co.orange.presentation.detail import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView -import co.orange.domain.entity.response.OptionModel +import co.orange.domain.entity.response.ProductOptionModel import kr.genti.presentation.databinding.ItemOptionBinding class OptionViewHolder( val binding: ItemOptionBinding, private val itemClick: (Int, Long, Long) -> Unit, ) : RecyclerView.ViewHolder(binding.root) { - var selectedItemId: Long = -1 var selectedPosition: Int = -1 - fun onBind(item: OptionModel, position: Int) { + fun onBind( + item: ProductOptionModel, + position: Int, + ) { selectedItemId = item.optionId selectedPosition = position with(binding) { @@ -22,16 +24,16 @@ class OptionViewHolder( rvOptionDetail.isVisible = !rvOptionDetail.isVisible btnToggle.isSelected = !btnToggle.isSelected } - rvOptionDetail.adapter = OptionDetailAdapter( - itemClick = ::initItemClickListener - ).apply { - addList(item.optionDetailList) - } + rvOptionDetail.adapter = + OptionDetailAdapter( + itemClick = ::initItemClickListener, + ).apply { + addList(item.optionDetailList) + } } } private fun initItemClickListener(optionDetailId: Long) { itemClick(selectedPosition, selectedItemId, optionDetailId) } - -} \ No newline at end of file +} From 727725a23eaa116f4e904b36afbfd26ac14513d4 Mon Sep 17 00:00:00 2001 From: Sangho Kim Date: Fri, 12 Jul 2024 16:17:37 +0900 Subject: [PATCH 3/6] =?UTF-8?q?[ADD/#42]=20=EC=83=81=ED=92=88=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20API=20data=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../orange/data/dataSource/DetailDataSource.kt | 8 ++++++++ .../data/dataSourceImpl/DetailDataSourceImpl.kt | 15 +++++++++++++++ .../data/repositoryImpl/DetailRepositoryImpl.kt | 17 +++++++++++++++++ .../co/orange/data/service/DetailService.kt | 13 +++++++++++++ 4 files changed, 53 insertions(+) create mode 100644 data/src/main/java/co/orange/data/dataSource/DetailDataSource.kt create mode 100644 data/src/main/java/co/orange/data/dataSourceImpl/DetailDataSourceImpl.kt create mode 100644 data/src/main/java/co/orange/data/repositoryImpl/DetailRepositoryImpl.kt create mode 100644 data/src/main/java/co/orange/data/service/DetailService.kt diff --git a/data/src/main/java/co/orange/data/dataSource/DetailDataSource.kt b/data/src/main/java/co/orange/data/dataSource/DetailDataSource.kt new file mode 100644 index 00000000..1a179d4d --- /dev/null +++ b/data/src/main/java/co/orange/data/dataSource/DetailDataSource.kt @@ -0,0 +1,8 @@ +package co.orange.data.dataSource + +import co.orange.data.dto.BaseResponse +import co.orange.data.dto.response.ProductDetailDto + +interface DetailDataSource { + suspend fun getHomeData(id: String): BaseResponse +} diff --git a/data/src/main/java/co/orange/data/dataSourceImpl/DetailDataSourceImpl.kt b/data/src/main/java/co/orange/data/dataSourceImpl/DetailDataSourceImpl.kt new file mode 100644 index 00000000..88579754 --- /dev/null +++ b/data/src/main/java/co/orange/data/dataSourceImpl/DetailDataSourceImpl.kt @@ -0,0 +1,15 @@ +package co.orange.data.dataSourceImpl + +import co.orange.data.dataSource.DetailDataSource +import co.orange.data.dto.BaseResponse +import co.orange.data.dto.response.ProductDetailDto +import co.orange.data.service.DetailService +import javax.inject.Inject + +data class DetailDataSourceImpl + @Inject + constructor( + private val detailService: DetailService, + ) : DetailDataSource { + override suspend fun getHomeData(id: String): BaseResponse = detailService.getProductDetail(id) + } diff --git a/data/src/main/java/co/orange/data/repositoryImpl/DetailRepositoryImpl.kt b/data/src/main/java/co/orange/data/repositoryImpl/DetailRepositoryImpl.kt new file mode 100644 index 00000000..fde0d4dc --- /dev/null +++ b/data/src/main/java/co/orange/data/repositoryImpl/DetailRepositoryImpl.kt @@ -0,0 +1,17 @@ +package co.orange.data.repositoryImpl + +import co.orange.data.dataSource.DetailDataSource +import co.orange.domain.entity.response.ProductDetailModel +import co.orange.domain.repository.DetailRepository +import javax.inject.Inject + +class DetailRepositoryImpl + @Inject + constructor( + private val detailDataSource: DetailDataSource, + ) : DetailRepository { + override suspend fun getProductDetail(id: String): Result = + runCatching { + detailDataSource.getHomeData(id).data.toModel() + } + } diff --git a/data/src/main/java/co/orange/data/service/DetailService.kt b/data/src/main/java/co/orange/data/service/DetailService.kt new file mode 100644 index 00000000..51801016 --- /dev/null +++ b/data/src/main/java/co/orange/data/service/DetailService.kt @@ -0,0 +1,13 @@ +package co.orange.data.service + +import co.orange.data.dto.BaseResponse +import co.orange.data.dto.response.ProductDetailDto +import retrofit2.http.Body +import retrofit2.http.GET + +interface DetailService { + @GET("/api/v1/home/product") + suspend fun getProductDetail( + @Body id: String, + ): BaseResponse +} From 4a90f8ab9a4decc940d9b509e158151b040cd9b6 Mon Sep 17 00:00:00 2001 From: Sangho Kim Date: Sat, 13 Jul 2024 05:09:52 +0900 Subject: [PATCH 4/6] =?UTF-8?q?[ADD/#42]=20=EC=83=81=ED=92=88=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20API=20di=20=EB=AA=A8=EB=93=88?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/co/orange/ddanzi/di/DataSourceModule.kt | 6 ++++++ app/src/main/java/co/orange/ddanzi/di/RepositoryModule.kt | 6 ++++++ app/src/main/java/co/orange/ddanzi/di/ServiceModule.kt | 7 +++++++ 3 files changed, 19 insertions(+) diff --git a/app/src/main/java/co/orange/ddanzi/di/DataSourceModule.kt b/app/src/main/java/co/orange/ddanzi/di/DataSourceModule.kt index e298f2b9..b956bd13 100644 --- a/app/src/main/java/co/orange/ddanzi/di/DataSourceModule.kt +++ b/app/src/main/java/co/orange/ddanzi/di/DataSourceModule.kt @@ -1,8 +1,10 @@ package co.orange.ddanzi.di import co.orange.data.dataSource.AuthDataSource +import co.orange.data.dataSource.DetailDataSource import co.orange.data.dataSource.HomeDataSource import co.orange.data.dataSourceImpl.AuthDataSourceImpl +import co.orange.data.dataSourceImpl.DetailDataSourceImpl import co.orange.data.dataSourceImpl.HomeDataSourceImpl import dagger.Module import dagger.Provides @@ -20,4 +22,8 @@ object DataSourceModule { @Provides @Singleton fun provideHomeDataSource(homeDataSourceImpl: HomeDataSourceImpl): HomeDataSource = homeDataSourceImpl + + @Provides + @Singleton + fun provideDetailDataSource(detailDataSourceImpl: DetailDataSourceImpl): DetailDataSource = detailDataSourceImpl } diff --git a/app/src/main/java/co/orange/ddanzi/di/RepositoryModule.kt b/app/src/main/java/co/orange/ddanzi/di/RepositoryModule.kt index 90793ece..45bedbd2 100644 --- a/app/src/main/java/co/orange/ddanzi/di/RepositoryModule.kt +++ b/app/src/main/java/co/orange/ddanzi/di/RepositoryModule.kt @@ -1,8 +1,10 @@ package co.orange.ddanzi.di import co.orange.data.repositoryImpl.AuthRepositoryImpl +import co.orange.data.repositoryImpl.DetailRepositoryImpl import co.orange.data.repositoryImpl.HomeRepositoryImpl import co.orange.domain.repository.AuthRepository +import co.orange.domain.repository.DetailRepository import co.orange.domain.repository.HomeRepository import dagger.Module import dagger.Provides @@ -20,4 +22,8 @@ object RepositoryModule { @Provides @Singleton fun provideHomeRepository(homeRepositoryImpl: HomeRepositoryImpl): HomeRepository = homeRepositoryImpl + + @Provides + @Singleton + fun provideDetailRepository(detailRepositoryImpl: DetailRepositoryImpl): DetailRepository = detailRepositoryImpl } diff --git a/app/src/main/java/co/orange/ddanzi/di/ServiceModule.kt b/app/src/main/java/co/orange/ddanzi/di/ServiceModule.kt index 8942fb7e..54005b6b 100644 --- a/app/src/main/java/co/orange/ddanzi/di/ServiceModule.kt +++ b/app/src/main/java/co/orange/ddanzi/di/ServiceModule.kt @@ -1,6 +1,7 @@ package co.orange.ddanzi.di import co.orange.data.service.AuthService +import co.orange.data.service.DetailService import co.orange.data.service.HomeService import dagger.Module import dagger.Provides @@ -23,4 +24,10 @@ object ServiceModule { fun provideHomeService( @RetrofitQualifier.NOTOKEN retrofit: Retrofit, ): HomeService = retrofit.create(HomeService::class.java) + + @Provides + @Singleton + fun provideDetailService( + @RetrofitQualifier.NOTOKEN retrofit: Retrofit, + ): DetailService = retrofit.create(DetailService::class.java) } From e3f7e33adf6658663a7fb4ed9c648486f3a6a6df Mon Sep 17 00:00:00 2001 From: Sangho Kim Date: Sat, 13 Jul 2024 05:45:59 +0900 Subject: [PATCH 5/6] =?UTF-8?q?[FEAT/#42]=20=EC=83=81=ED=92=88=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../buy/confirm/BuyConfirmActivity.kt | 4 +- .../buy/confirm/BuyConfirmViewModel.kt | 44 ++++++------- .../buy/finished/BuyFinishedActivity.kt | 4 +- .../buy/finished/BuyFinishedViewModel.kt | 62 +++++++++--------- .../presentation/buy/info/BuyInfoActivity.kt | 4 +- .../presentation/buy/info/BuyInfoViewModel.kt | 62 +++++++++--------- .../presentation/buy/push/BuyPushActivity.kt | 4 +- .../presentation/detail/DetailActivity.kt | 24 +++++-- .../presentation/detail/DetailViewModel.kt | 65 ++++++++++--------- .../presentation/detail/OptionBottomSheet.kt | 8 +-- 10 files changed, 149 insertions(+), 132 deletions(-) diff --git a/presentation/src/main/java/co/orange/presentation/buy/confirm/BuyConfirmActivity.kt b/presentation/src/main/java/co/orange/presentation/buy/confirm/BuyConfirmActivity.kt index 35afbce9..31194d6f 100644 --- a/presentation/src/main/java/co/orange/presentation/buy/confirm/BuyConfirmActivity.kt +++ b/presentation/src/main/java/co/orange/presentation/buy/confirm/BuyConfirmActivity.kt @@ -56,7 +56,7 @@ class BuyConfirmActivity : BaseActivity(R.layout.acti } private fun getIntentInfo() { - viewModel.productId = intent.getLongExtra(EXTRA_PRODUCT_ID, -1) + viewModel.productId = intent.getStringExtra(EXTRA_PRODUCT_ID).orEmpty() } private fun setIntentUi(item: BuyInfoModel) { @@ -79,7 +79,7 @@ class BuyConfirmActivity : BaseActivity(R.layout.acti @JvmStatic fun createIntent( context: Context, - productId: Long, + productId: String, ): Intent = Intent(context, BuyConfirmActivity::class.java).apply { putExtra(EXTRA_PRODUCT_ID, productId) diff --git a/presentation/src/main/java/co/orange/presentation/buy/confirm/BuyConfirmViewModel.kt b/presentation/src/main/java/co/orange/presentation/buy/confirm/BuyConfirmViewModel.kt index 4730655f..9764621a 100644 --- a/presentation/src/main/java/co/orange/presentation/buy/confirm/BuyConfirmViewModel.kt +++ b/presentation/src/main/java/co/orange/presentation/buy/confirm/BuyConfirmViewModel.kt @@ -8,27 +8,27 @@ import javax.inject.Inject @HiltViewModel class BuyConfirmViewModel -@Inject -constructor( - // private val feedRepository: FeedRepository, -) : ViewModel() { + @Inject + constructor( + // private val feedRepository: FeedRepository, + ) : ViewModel() { + var productId: String = "" - var productId: Long = -1 - - val mockBuyInfo = BuyInfoModel( - "상품이름은 한줄로만 보여줄거에야야야야야야", - "https://github.com/Marchbreeze/Marchbreeze/assets/97405341/cd2c0454-92b4-41e7-ae2f-319f83e2426f", - 24000, - listOf( - AddressInfoModel( - "김상호", - "04567", - "서울특벌시 성동구 성수이로 137 107동 903호", - "010-3259-0327" + val mockBuyInfo = + BuyInfoModel( + "상품이름은 한줄로만 보여줄거에야야야야야야", + "https://github.com/Marchbreeze/Marchbreeze/assets/97405341/cd2c0454-92b4-41e7-ae2f-319f83e2426f", + 24000, + listOf( + AddressInfoModel( + "김상호", + "04567", + "서울특벌시 성동구 성수이로 137 107동 903호", + "010-3259-0327", + ), + ), + 3000, + 350, + 21350, ) - ), - 3000, - 350, - 21350 - ) -} \ No newline at end of file + } diff --git a/presentation/src/main/java/co/orange/presentation/buy/finished/BuyFinishedActivity.kt b/presentation/src/main/java/co/orange/presentation/buy/finished/BuyFinishedActivity.kt index f6722e8e..c15b43a2 100644 --- a/presentation/src/main/java/co/orange/presentation/buy/finished/BuyFinishedActivity.kt +++ b/presentation/src/main/java/co/orange/presentation/buy/finished/BuyFinishedActivity.kt @@ -52,7 +52,7 @@ class BuyFinishedActivity : } private fun getIntentInfo() { - viewModel.productId = intent.getLongExtra(EXTRA_PRODUCT_ID, -1) + viewModel.productId = intent.getStringExtra(EXTRA_PRODUCT_ID).orEmpty() } private fun setIntentUi(item: BuyDetailModel) { @@ -85,7 +85,7 @@ class BuyFinishedActivity : @JvmStatic fun createIntent( context: Context, - productId: Long, + productId: String, ): Intent = Intent(context, BuyFinishedActivity::class.java).apply { putExtra(EXTRA_PRODUCT_ID, productId) diff --git a/presentation/src/main/java/co/orange/presentation/buy/finished/BuyFinishedViewModel.kt b/presentation/src/main/java/co/orange/presentation/buy/finished/BuyFinishedViewModel.kt index 5b74ec54..01aed439 100644 --- a/presentation/src/main/java/co/orange/presentation/buy/finished/BuyFinishedViewModel.kt +++ b/presentation/src/main/java/co/orange/presentation/buy/finished/BuyFinishedViewModel.kt @@ -10,36 +10,36 @@ import javax.inject.Inject @HiltViewModel class BuyFinishedViewModel -@Inject -constructor( - // private val feedRepository: FeedRepository, -) : ViewModel() { + @Inject + constructor( + // private val feedRepository: FeedRepository, + ) : ViewModel() { + var productId: String = "" - var productId: Long = -1 - - val mockBuyInfo = BuyDetailModel( - "123e4567-e89b-12d3-a456-426614174000", - OrderStatus.ORDER_PLACED, - "상품이름은 한줄로만 보여줄거에야야야야야야", - "https://github.com/Marchbreeze/Marchbreeze/assets/97405341/cd2c0454-92b4-41e7-ae2f-319f83e2426f", - 24000, - "등둔", - listOf( - AddressInfoModel( - "김상호", - "04567", - "서울특벌시 성동구 성수이로 137 107동 903호", - "010-3259-0327" - ) - ), - listOf( - PaymentInfoModel( - "NAVERPAY", - "2024.06.06" + val mockBuyInfo = + BuyDetailModel( + "123e4567-e89b-12d3-a456-426614174000", + OrderStatus.ORDER_PLACED, + "상품이름은 한줄로만 보여줄거에야야야야야야", + "https://github.com/Marchbreeze/Marchbreeze/assets/97405341/cd2c0454-92b4-41e7-ae2f-319f83e2426f", + 24000, + "등둔", + listOf( + AddressInfoModel( + "김상호", + "04567", + "서울특벌시 성동구 성수이로 137 107동 903호", + "010-3259-0327", + ), + ), + listOf( + PaymentInfoModel( + "NAVERPAY", + "2024.06.06", + ), + ), + 3000, + 350, + 21350, ) - ), - 3000, - 350, - 21350 - ) -} \ No newline at end of file + } diff --git a/presentation/src/main/java/co/orange/presentation/buy/info/BuyInfoActivity.kt b/presentation/src/main/java/co/orange/presentation/buy/info/BuyInfoActivity.kt index f4a67c05..4b396a18 100644 --- a/presentation/src/main/java/co/orange/presentation/buy/info/BuyInfoActivity.kt +++ b/presentation/src/main/java/co/orange/presentation/buy/info/BuyInfoActivity.kt @@ -38,7 +38,7 @@ class BuyInfoActivity : } private fun getIntentInfo() { - viewModel.productId = intent.getLongExtra(EXTRA_PRODUCT_ID, -1) + viewModel.productId = intent.getStringExtra(EXTRA_PRODUCT_ID).orEmpty() } private fun setIntentUi(item: BuyDetailModel) { @@ -72,7 +72,7 @@ class BuyInfoActivity : @JvmStatic fun createIntent( context: Context, - productId: Long, + productId: String, ): Intent = Intent(context, BuyInfoActivity::class.java).apply { putExtra(EXTRA_PRODUCT_ID, productId) diff --git a/presentation/src/main/java/co/orange/presentation/buy/info/BuyInfoViewModel.kt b/presentation/src/main/java/co/orange/presentation/buy/info/BuyInfoViewModel.kt index 9476a0db..147e9660 100644 --- a/presentation/src/main/java/co/orange/presentation/buy/info/BuyInfoViewModel.kt +++ b/presentation/src/main/java/co/orange/presentation/buy/info/BuyInfoViewModel.kt @@ -10,36 +10,36 @@ import javax.inject.Inject @HiltViewModel class BuyInfoViewModel -@Inject -constructor( - // private val feedRepository: FeedRepository, -) : ViewModel() { + @Inject + constructor( + // private val feedRepository: FeedRepository, + ) : ViewModel() { + var productId: String = "" - var productId: Long = -1 - - val mockBuyInfo = BuyDetailModel( - "123e4567-e89b-12d3-a456-426614174000", - OrderStatus.ORDER_PLACED, - "상품이름은 한줄로만 보여줄거에야야야야야야", - "https://github.com/Marchbreeze/Marchbreeze/assets/97405341/cd2c0454-92b4-41e7-ae2f-319f83e2426f", - 24000, - "등둔", - listOf( - AddressInfoModel( - "김상호", - "04567", - "서울특벌시 성동구 성수이로 137 107동 903호", - "010-3259-0327" - ) - ), - listOf( - PaymentInfoModel( - "NAVERPAY", - "2024.06.06" + val mockBuyInfo = + BuyDetailModel( + "123e4567-e89b-12d3-a456-426614174000", + OrderStatus.ORDER_PLACED, + "상품이름은 한줄로만 보여줄거에야야야야야야", + "https://github.com/Marchbreeze/Marchbreeze/assets/97405341/cd2c0454-92b4-41e7-ae2f-319f83e2426f", + 24000, + "등둔", + listOf( + AddressInfoModel( + "김상호", + "04567", + "서울특벌시 성동구 성수이로 137 107동 903호", + "010-3259-0327", + ), + ), + listOf( + PaymentInfoModel( + "NAVERPAY", + "2024.06.06", + ), + ), + 3000, + 350, + 21350, ) - ), - 3000, - 350, - 21350 - ) -} \ No newline at end of file + } diff --git a/presentation/src/main/java/co/orange/presentation/buy/push/BuyPushActivity.kt b/presentation/src/main/java/co/orange/presentation/buy/push/BuyPushActivity.kt index a3f2d211..efa17178 100644 --- a/presentation/src/main/java/co/orange/presentation/buy/push/BuyPushActivity.kt +++ b/presentation/src/main/java/co/orange/presentation/buy/push/BuyPushActivity.kt @@ -39,7 +39,7 @@ class BuyPushActivity : BaseActivity(R.layout.activity_push } private fun navigateToFinishedActivity() { - val productId = intent.getLongExtra(EXTRA_PRODUCT_ID, -1) + val productId = intent.getStringExtra(EXTRA_PRODUCT_ID).orEmpty() BuyFinishedActivity.createIntent(this, productId).apply { startActivity(this) } @@ -51,7 +51,7 @@ class BuyPushActivity : BaseActivity(R.layout.activity_push @JvmStatic fun createIntent( context: Context, - productId: Long, + productId: String, ): Intent = Intent(context, BuyPushActivity::class.java).apply { putExtra(EXTRA_PRODUCT_ID, productId) diff --git a/presentation/src/main/java/co/orange/presentation/detail/DetailActivity.kt b/presentation/src/main/java/co/orange/presentation/detail/DetailActivity.kt index cc5141c8..cfdeaf21 100644 --- a/presentation/src/main/java/co/orange/presentation/detail/DetailActivity.kt +++ b/presentation/src/main/java/co/orange/presentation/detail/DetailActivity.kt @@ -7,14 +7,21 @@ import android.net.Uri import android.os.Bundle import androidx.activity.viewModels import androidx.core.view.isVisible +import androidx.lifecycle.flowWithLifecycle +import androidx.lifecycle.lifecycleScope import co.orange.core.base.BaseActivity import co.orange.core.extension.breakLines import co.orange.core.extension.setNumberForm import co.orange.core.extension.setOnSingleClickListener import co.orange.core.extension.setOverThousand +import co.orange.core.extension.stringOf +import co.orange.core.extension.toast +import co.orange.core.state.UiState import co.orange.domain.entity.response.ProductDetailModel import coil.load import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import kr.genti.presentation.R import kr.genti.presentation.databinding.ActivityDetailBinding @@ -32,7 +39,7 @@ class DetailActivity : BaseActivity(R.layout.activity_det initLikeBtnListener() initPurchaseBtnListener() getIntentInfo() - setProduct(viewModel.mockProduct) + observeGetProductDetailState() } private fun initBackBtnListener() { @@ -42,8 +49,8 @@ class DetailActivity : BaseActivity(R.layout.activity_det private fun initDetailViewBtnListener() { binding.btnDetailView.setOnSingleClickListener { - if (viewModel.mockProduct.infoUrl.isNotEmpty()) { - startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(viewModel.mockProduct.infoUrl))) + if (viewModel.infoUrl.isNotEmpty()) { + startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(viewModel.infoUrl))) } } } @@ -77,6 +84,16 @@ class DetailActivity : BaseActivity(R.layout.activity_det } } + private fun observeGetProductDetailState() { + viewModel.getProductDetailState.flowWithLifecycle(lifecycle).onEach { state -> + when (state) { + is UiState.Success -> setProduct(state.data) + is UiState.Failure -> toast(stringOf(R.string.error_msg)) + else -> return@onEach + } + }.launchIn(lifecycleScope) + } + private fun setProduct(item: ProductDetailModel) { with(binding) { tvDetailTitle.text = item.name.breakLines() @@ -85,7 +102,6 @@ class DetailActivity : BaseActivity(R.layout.activity_det chipsDetailImminent.isVisible = item.isImminent tvDetailDiscountRate.text = item.discountRate.toString() tvDetailStockCount.text = item.stockCount.toString() - tvDetailLike.text = viewModel.mockProduct.interestCount.toString() tvDetailLike.text = item.interestCount.setOverThousand() } } diff --git a/presentation/src/main/java/co/orange/presentation/detail/DetailViewModel.kt b/presentation/src/main/java/co/orange/presentation/detail/DetailViewModel.kt index 751345a0..18a524a5 100644 --- a/presentation/src/main/java/co/orange/presentation/detail/DetailViewModel.kt +++ b/presentation/src/main/java/co/orange/presentation/detail/DetailViewModel.kt @@ -1,51 +1,52 @@ package co.orange.presentation.detail import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import co.orange.core.state.UiState import co.orange.domain.entity.response.ProductDetailModel import co.orange.domain.entity.response.ProductOptionModel +import co.orange.domain.repository.DetailRepository import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class DetailViewModel @Inject constructor( - // private val feedRepository: FeedRepository, + private val detailRepository: DetailRepository, ) : ViewModel() { var productId: String = "" var imageUrl: String = "" var originPrice: Int = 0 var salePrice: Int = 0 - val mockProduct = - ProductDetailModel( - "퓨어 오일 퍼퓸 10 ml 긴제목테스트트트트트", - "카테고리", - false, - true, - 30, - 12, - "", - 123, - listOf( - ProductOptionModel( - 1, - "색상", - listOf( - ProductOptionModel.OptionDetailModel(0, "네이비", true), - ProductOptionModel.OptionDetailModel(1, "블랙", true), - ), - ), - ProductOptionModel( - 2, - "사이즈", - listOf( - ProductOptionModel.OptionDetailModel(0, "S", true), - ProductOptionModel.OptionDetailModel(1, "M", true), - ProductOptionModel.OptionDetailModel(2, "L", true), - ProductOptionModel.OptionDetailModel(3, "XL", true), - ), - ), - ), - ) + var infoUrl: String = "" + var interestCount: Int = 0 + var optionList = listOf() + + private val _getProductDetailState = + MutableStateFlow>(UiState.Empty) + val getProductDetailState: StateFlow> = _getProductDetailState + + init { + getProductDetailFromServer() + } + + private fun getProductDetailFromServer() { + viewModelScope.launch { + detailRepository.getProductDetail(productId) + .onSuccess { + infoUrl = it.infoUrl + interestCount = it.interestCount + optionList = it.optionList + _getProductDetailState.value = UiState.Success(it) + } + .onFailure { + _getProductDetailState.value = UiState.Failure(it.message.toString()) + } + } + } } diff --git a/presentation/src/main/java/co/orange/presentation/detail/OptionBottomSheet.kt b/presentation/src/main/java/co/orange/presentation/detail/OptionBottomSheet.kt index 0ae7c411..5a4d5203 100644 --- a/presentation/src/main/java/co/orange/presentation/detail/OptionBottomSheet.kt +++ b/presentation/src/main/java/co/orange/presentation/detail/OptionBottomSheet.kt @@ -40,8 +40,8 @@ class OptionBottomSheet : private fun initDetailViewBtnListener() { binding.btnDetailView.setOnSingleClickListener { - if (viewModel.mockProduct.infoUrl.isNotEmpty()) { - startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(viewModel.mockProduct.infoUrl))) + if (viewModel.infoUrl.isNotEmpty()) { + startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(viewModel.infoUrl))) } } } @@ -75,10 +75,10 @@ class OptionBottomSheet : } private fun setInterestCount() { - viewModel.mockProduct.interestCount.setOverThousand() + viewModel.interestCount.setOverThousand() } private fun setOptionData() { - adapter.addList(viewModel.mockProduct.optionList) + adapter.addList(viewModel.optionList) } } From 46fe9df7d875e3eb36a1109072ec1e9fefc48209 Mon Sep 17 00:00:00 2001 From: Sangho Kim Date: Sat, 13 Jul 2024 06:08:02 +0900 Subject: [PATCH 6/6] =?UTF-8?q?[FEAT/#42]=20DeviceTokenInterceptor=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../di/{ => interceptor}/AuthInterceptor.kt | 2 +- .../di/interceptor/DeviceTokenInterceptor.kt | 26 ++++++++++++++ .../di/{ => module}/DataSourceModule.kt | 2 +- .../di/{ => module}/RepositoryModule.kt | 2 +- .../ddanzi/di/{ => module}/RetrofitModule.kt | 35 ++++++++++++++++++- .../ddanzi/di/{ => module}/ServiceModule.kt | 5 +-- .../di/{ => module}/SharedPrefModule.kt | 2 +- .../di/{ => qualifier}/RetrofitQualifier.kt | 6 +++- .../co/orange/data/local/UserSharedPref.kt | 1 + .../orange/data/local/UserSharedPrefImpl.kt | 5 +++ .../co/orange/data/service/DetailService.kt | 6 ++-- .../presentation/detail/DetailActivity.kt | 1 + .../presentation/detail/DetailViewModel.kt | 6 +--- 13 files changed, 83 insertions(+), 16 deletions(-) rename app/src/main/java/co/orange/ddanzi/di/{ => interceptor}/AuthInterceptor.kt (98%) create mode 100644 app/src/main/java/co/orange/ddanzi/di/interceptor/DeviceTokenInterceptor.kt rename app/src/main/java/co/orange/ddanzi/di/{ => module}/DataSourceModule.kt (96%) rename app/src/main/java/co/orange/ddanzi/di/{ => module}/RepositoryModule.kt (96%) rename app/src/main/java/co/orange/ddanzi/di/{ => module}/RetrofitModule.kt (74%) rename app/src/main/java/co/orange/ddanzi/di/{ => module}/ServiceModule.kt (85%) rename app/src/main/java/co/orange/ddanzi/di/{ => module}/SharedPrefModule.kt (95%) rename app/src/main/java/co/orange/ddanzi/di/{ => qualifier}/RetrofitQualifier.kt (64%) diff --git a/app/src/main/java/co/orange/ddanzi/di/AuthInterceptor.kt b/app/src/main/java/co/orange/ddanzi/di/interceptor/AuthInterceptor.kt similarity index 98% rename from app/src/main/java/co/orange/ddanzi/di/AuthInterceptor.kt rename to app/src/main/java/co/orange/ddanzi/di/interceptor/AuthInterceptor.kt index ab98b721..d1dbfa51 100644 --- a/app/src/main/java/co/orange/ddanzi/di/AuthInterceptor.kt +++ b/app/src/main/java/co/orange/ddanzi/di/interceptor/AuthInterceptor.kt @@ -1,4 +1,4 @@ -package co.orange.ddanzi.di +package co.orange.ddanzi.di.interceptor import android.content.Context import android.content.Intent diff --git a/app/src/main/java/co/orange/ddanzi/di/interceptor/DeviceTokenInterceptor.kt b/app/src/main/java/co/orange/ddanzi/di/interceptor/DeviceTokenInterceptor.kt new file mode 100644 index 00000000..a31191d5 --- /dev/null +++ b/app/src/main/java/co/orange/ddanzi/di/interceptor/DeviceTokenInterceptor.kt @@ -0,0 +1,26 @@ +package co.orange.ddanzi.di.interceptor + +import co.orange.data.local.UserSharedPref +import okhttp3.Interceptor +import okhttp3.Response +import javax.inject.Inject + +class DeviceTokenInterceptor + @Inject + constructor( + private val sharedPref: UserSharedPref, + ) : Interceptor { + override fun intercept(chain: Interceptor.Chain): Response { + val originalRequest = chain.request() + val newRequest = + originalRequest.newBuilder() + .header(AUTHORIZATION, "$BEARER ${sharedPref.accessToken}") + .build() + return chain.proceed(newRequest) + } + + companion object { + private const val BEARER = "Bearer" + private const val AUTHORIZATION = "Authorization" + } + } diff --git a/app/src/main/java/co/orange/ddanzi/di/DataSourceModule.kt b/app/src/main/java/co/orange/ddanzi/di/module/DataSourceModule.kt similarity index 96% rename from app/src/main/java/co/orange/ddanzi/di/DataSourceModule.kt rename to app/src/main/java/co/orange/ddanzi/di/module/DataSourceModule.kt index b956bd13..b6ee4687 100644 --- a/app/src/main/java/co/orange/ddanzi/di/DataSourceModule.kt +++ b/app/src/main/java/co/orange/ddanzi/di/module/DataSourceModule.kt @@ -1,4 +1,4 @@ -package co.orange.ddanzi.di +package co.orange.ddanzi.di.module import co.orange.data.dataSource.AuthDataSource import co.orange.data.dataSource.DetailDataSource diff --git a/app/src/main/java/co/orange/ddanzi/di/RepositoryModule.kt b/app/src/main/java/co/orange/ddanzi/di/module/RepositoryModule.kt similarity index 96% rename from app/src/main/java/co/orange/ddanzi/di/RepositoryModule.kt rename to app/src/main/java/co/orange/ddanzi/di/module/RepositoryModule.kt index 45bedbd2..4c84daf7 100644 --- a/app/src/main/java/co/orange/ddanzi/di/RepositoryModule.kt +++ b/app/src/main/java/co/orange/ddanzi/di/module/RepositoryModule.kt @@ -1,4 +1,4 @@ -package co.orange.ddanzi.di +package co.orange.ddanzi.di.module import co.orange.data.repositoryImpl.AuthRepositoryImpl import co.orange.data.repositoryImpl.DetailRepositoryImpl diff --git a/app/src/main/java/co/orange/ddanzi/di/RetrofitModule.kt b/app/src/main/java/co/orange/ddanzi/di/module/RetrofitModule.kt similarity index 74% rename from app/src/main/java/co/orange/ddanzi/di/RetrofitModule.kt rename to app/src/main/java/co/orange/ddanzi/di/module/RetrofitModule.kt index 8f082a45..8ebcd7ac 100644 --- a/app/src/main/java/co/orange/ddanzi/di/RetrofitModule.kt +++ b/app/src/main/java/co/orange/ddanzi/di/module/RetrofitModule.kt @@ -1,8 +1,11 @@ -package co.orange.ddanzi.di +package co.orange.ddanzi.di.module import co.orange.core.extension.isJsonArray import co.orange.core.extension.isJsonObject import co.orange.ddanzi.BuildConfig.BASE_URL +import co.orange.ddanzi.di.interceptor.AuthInterceptor +import co.orange.ddanzi.di.interceptor.DeviceTokenInterceptor +import co.orange.ddanzi.di.qualifier.RetrofitQualifier import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory import dagger.Module import dagger.Provides @@ -64,6 +67,11 @@ object RetrofitModule { @RetrofitQualifier.JWT fun provideAuthInterceptor(authInterceptor: AuthInterceptor): Interceptor = authInterceptor + @Provides + @Singleton + @RetrofitQualifier.DEVICE + fun provideDeviceTokenInterceptor(deviceTokenInterceptor: DeviceTokenInterceptor): Interceptor = deviceTokenInterceptor + @Provides @Singleton @RetrofitQualifier.JWT @@ -84,6 +92,18 @@ object RetrofitModule { .addInterceptor(loggingInterceptor) .build() + @Provides + @Singleton + @RetrofitQualifier.DEVICE + fun provideDeviceOkHttpClient( + loggingInterceptor: Interceptor, + @RetrofitQualifier.DEVICE deviceTokenInterceptor: Interceptor, + ): OkHttpClient = + OkHttpClient.Builder() + .addInterceptor(loggingInterceptor) + .addInterceptor(deviceTokenInterceptor) + .build() + @Provides @Singleton @RetrofitQualifier.JWT @@ -109,4 +129,17 @@ object RetrofitModule { .client(client) .addConverterFactory(factory) .build() + + @Provides + @Singleton + @RetrofitQualifier.DEVICE + fun provideDeviceRetrofit( + @RetrofitQualifier.DEVICE client: OkHttpClient, + factory: Converter.Factory, + ): Retrofit = + Retrofit.Builder() + .baseUrl(BASE_URL) + .client(client) + .addConverterFactory(factory) + .build() } diff --git a/app/src/main/java/co/orange/ddanzi/di/ServiceModule.kt b/app/src/main/java/co/orange/ddanzi/di/module/ServiceModule.kt similarity index 85% rename from app/src/main/java/co/orange/ddanzi/di/ServiceModule.kt rename to app/src/main/java/co/orange/ddanzi/di/module/ServiceModule.kt index 54005b6b..2754b225 100644 --- a/app/src/main/java/co/orange/ddanzi/di/ServiceModule.kt +++ b/app/src/main/java/co/orange/ddanzi/di/module/ServiceModule.kt @@ -1,8 +1,9 @@ -package co.orange.ddanzi.di +package co.orange.ddanzi.di.module import co.orange.data.service.AuthService import co.orange.data.service.DetailService import co.orange.data.service.HomeService +import co.orange.ddanzi.di.qualifier.RetrofitQualifier import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -28,6 +29,6 @@ object ServiceModule { @Provides @Singleton fun provideDetailService( - @RetrofitQualifier.NOTOKEN retrofit: Retrofit, + @RetrofitQualifier.DEVICE retrofit: Retrofit, ): DetailService = retrofit.create(DetailService::class.java) } diff --git a/app/src/main/java/co/orange/ddanzi/di/SharedPrefModule.kt b/app/src/main/java/co/orange/ddanzi/di/module/SharedPrefModule.kt similarity index 95% rename from app/src/main/java/co/orange/ddanzi/di/SharedPrefModule.kt rename to app/src/main/java/co/orange/ddanzi/di/module/SharedPrefModule.kt index 6a8d437b..414f830a 100644 --- a/app/src/main/java/co/orange/ddanzi/di/SharedPrefModule.kt +++ b/app/src/main/java/co/orange/ddanzi/di/module/SharedPrefModule.kt @@ -1,4 +1,4 @@ -package co.orange.ddanzi.di +package co.orange.ddanzi.di.module import android.content.Context import android.content.SharedPreferences diff --git a/app/src/main/java/co/orange/ddanzi/di/RetrofitQualifier.kt b/app/src/main/java/co/orange/ddanzi/di/qualifier/RetrofitQualifier.kt similarity index 64% rename from app/src/main/java/co/orange/ddanzi/di/RetrofitQualifier.kt rename to app/src/main/java/co/orange/ddanzi/di/qualifier/RetrofitQualifier.kt index b7fc3adc..90b285d5 100644 --- a/app/src/main/java/co/orange/ddanzi/di/RetrofitQualifier.kt +++ b/app/src/main/java/co/orange/ddanzi/di/qualifier/RetrofitQualifier.kt @@ -1,4 +1,4 @@ -package co.orange.ddanzi.di +package co.orange.ddanzi.di.qualifier import javax.inject.Qualifier @@ -10,4 +10,8 @@ object RetrofitQualifier { @Qualifier @Retention(AnnotationRetention.BINARY) annotation class NOTOKEN + + @Qualifier + @Retention(AnnotationRetention.BINARY) + annotation class DEVICE } diff --git a/data/src/main/java/co/orange/data/local/UserSharedPref.kt b/data/src/main/java/co/orange/data/local/UserSharedPref.kt index 6577cf66..aa51a550 100644 --- a/data/src/main/java/co/orange/data/local/UserSharedPref.kt +++ b/data/src/main/java/co/orange/data/local/UserSharedPref.kt @@ -3,6 +3,7 @@ package co.orange.data.local interface UserSharedPref { var accessToken: String var refreshToken: String + var deviceToken: String var userId: Long fun clearInfo() diff --git a/data/src/main/java/co/orange/data/local/UserSharedPrefImpl.kt b/data/src/main/java/co/orange/data/local/UserSharedPrefImpl.kt index 23362473..bea77172 100644 --- a/data/src/main/java/co/orange/data/local/UserSharedPrefImpl.kt +++ b/data/src/main/java/co/orange/data/local/UserSharedPrefImpl.kt @@ -17,6 +17,10 @@ class UserSharedPrefImpl get() = dataStore.getString(REFRESH_TOKEN, "").orEmpty() set(value) = dataStore.edit { putString(REFRESH_TOKEN, value) } + override var deviceToken: String + get() = dataStore.getString(DEVICE_TOKEN, "").orEmpty() + set(value) = dataStore.edit { putString(DEVICE_TOKEN, value) } + override var userId: Long get() = dataStore.getLong(USER_ID, 0L) set(value) = dataStore.edit { putLong(USER_ID, value) } @@ -28,6 +32,7 @@ class UserSharedPrefImpl companion object { private const val ACCESS_TOKEN = "ACCESS_TOKEN" private const val REFRESH_TOKEN = "REFRESH_TOKEN" + private const val DEVICE_TOKEN = "DEVICE_TOKEN" private const val USER_ID = "USER_ID" } } diff --git a/data/src/main/java/co/orange/data/service/DetailService.kt b/data/src/main/java/co/orange/data/service/DetailService.kt index 51801016..af985ed4 100644 --- a/data/src/main/java/co/orange/data/service/DetailService.kt +++ b/data/src/main/java/co/orange/data/service/DetailService.kt @@ -2,12 +2,12 @@ package co.orange.data.service import co.orange.data.dto.BaseResponse import co.orange.data.dto.response.ProductDetailDto -import retrofit2.http.Body import retrofit2.http.GET +import retrofit2.http.Path interface DetailService { - @GET("/api/v1/home/product") + @GET("/api/v1/home/product/{id}") suspend fun getProductDetail( - @Body id: String, + @Path("id") id: String, ): BaseResponse } diff --git a/presentation/src/main/java/co/orange/presentation/detail/DetailActivity.kt b/presentation/src/main/java/co/orange/presentation/detail/DetailActivity.kt index cfdeaf21..d3e84f19 100644 --- a/presentation/src/main/java/co/orange/presentation/detail/DetailActivity.kt +++ b/presentation/src/main/java/co/orange/presentation/detail/DetailActivity.kt @@ -73,6 +73,7 @@ class DetailActivity : BaseActivity(R.layout.activity_det imageUrl = intent.getStringExtra(EXTRA_PRODUCT_URL).orEmpty() originPrice = intent.getIntExtra(EXTRA_ORIGIN_PRICE, 0) salePrice = intent.getIntExtra(EXTRA_SALE_PRICE, 0) + getProductDetailFromServer() } with(binding) { ivDetailProduct.load(viewModel.imageUrl) diff --git a/presentation/src/main/java/co/orange/presentation/detail/DetailViewModel.kt b/presentation/src/main/java/co/orange/presentation/detail/DetailViewModel.kt index 18a524a5..60bdf111 100644 --- a/presentation/src/main/java/co/orange/presentation/detail/DetailViewModel.kt +++ b/presentation/src/main/java/co/orange/presentation/detail/DetailViewModel.kt @@ -31,11 +31,7 @@ class DetailViewModel MutableStateFlow>(UiState.Empty) val getProductDetailState: StateFlow> = _getProductDetailState - init { - getProductDetailFromServer() - } - - private fun getProductDetailFromServer() { + fun getProductDetailFromServer() { viewModelScope.launch { detailRepository.getProductDetail(productId) .onSuccess {