-
Notifications
You must be signed in to change notification settings - Fork 0
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] 추천 뷰 구현 #24
[feat] 추천 뷰 구현 #24
Changes from 42 commits
b8d2853
f9b4b24
63dbe7c
774436d
5420bfd
de1ce2f
08a8616
cd39e35
4a03d6a
6c347da
a2c5329
80ee282
c6c2d65
7c207f0
571e931
682aefb
6ed0a56
463a144
2b00572
2584ce8
35e3f95
79991b0
7b0382f
14d72aa
e7694d3
825a921
909ca51
3b71de4
0e39b30
69b76da
4521336
0f4ebc4
fc213b6
796f9c2
fbc2cbf
a1bb216
aaed73b
97ffef0
d45a1c9
f0c4021
e43ca75
c129664
7697202
ea971f7
b7670e4
4581e9f
62c57b7
e0ffa71
39de15c
9de9011
cb6513c
d1948ad
4fae373
beac447
6eee5d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,11 @@ | ||
package org.sopt.kream.data.datasource | ||
|
||
import org.sopt.kream.data.model.response.ResponseRecommendProductDto | ||
import org.sopt.kream.data.model.response.ResponseSearchProductDto | ||
import org.sopt.kream.util.base.BaseResponse | ||
|
||
interface ProductRemoteDataSource { | ||
suspend fun getSearchProduct(findName: String): BaseResponse<ResponseSearchProductDto> | ||
|
||
suspend fun getRecommendProduct(memberId: Int): BaseResponse<ResponseRecommendProductDto> | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package org.sopt.kream.data.mapper | ||
|
||
import org.sopt.kream.data.model.response.ResponseRecommendProductDto.ResponseForYouProductDto | ||
import org.sopt.kream.domain.model.RecommendForYouProductModel | ||
|
||
fun ResponseForYouProductDto.toRecommendForYouProductModel() = | ||
RecommendForYouProductModel( | ||
thumbnailUrl = this.thumbnailUrl, | ||
brandTitle = this.brandTitle, | ||
engTitle = this.engTitle, | ||
price = this.price, | ||
transactionCount = this.transactionCount, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package org.sopt.kream.data.mapper | ||
|
||
import org.sopt.kream.data.model.response.ResponseRecommendProductDto.ResponseJustDroppedProductDto | ||
import org.sopt.kream.domain.model.RecommendJustDroppedProductModel | ||
|
||
fun ResponseJustDroppedProductDto.toRecommendJustDroppedProductModel() = | ||
RecommendJustDroppedProductModel( | ||
thumbnailUrl = this.thumbnailUrl, | ||
brandTitle = this.brandTitle, | ||
engTitle = this.engTitle, | ||
price = this.price, | ||
transactionCount = this.transactionCount, | ||
isScrap = this.isScrap, | ||
isFast = this.isFast, | ||
isFreeDeliver = this.isFreeDeliver, | ||
isSave = this.isSave, | ||
isCoupon = this.isCoupon, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package org.sopt.kream.data.mapper | ||
|
||
import org.sopt.kream.data.model.response.ResponseRecommendProductDto | ||
import org.sopt.kream.domain.model.RecommendProductModel | ||
|
||
fun ResponseRecommendProductDto.toRecommendProductModel() = | ||
RecommendProductModel( | ||
recommendForYouProducts = this.forYouList.map { it.toRecommendForYouProductModel() }, | ||
recommendJustDroppedProducts = this.justDropList.map { it.toRecommendJustDroppedProductModel() }, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package org.sopt.kream.data.model.response | ||
|
||
import kotlinx.serialization.SerialName | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class ResponseRecommendProductDto( | ||
@SerialName("forYouList") | ||
val forYouList: List<ResponseForYouProductDto>, | ||
@SerialName("justDropList") | ||
val justDropList: List<ResponseJustDroppedProductDto>, | ||
) { | ||
@Serializable | ||
data class ResponseForYouProductDto( | ||
@SerialName("thumbnailUrl") | ||
val thumbnailUrl: String, | ||
@SerialName("brandTitle") | ||
val brandTitle: String, | ||
@SerialName("engTitle") | ||
val engTitle: String, | ||
@SerialName("price") | ||
val price: String, | ||
@SerialName("transactionCount") | ||
val transactionCount: String, | ||
) | ||
|
||
@Serializable | ||
data class ResponseJustDroppedProductDto( | ||
@SerialName("thumbnailUrl") | ||
val thumbnailUrl: String, | ||
@SerialName("brandTitle") | ||
val brandTitle: String, | ||
@SerialName("engTitle") | ||
val engTitle: String, | ||
@SerialName("price") | ||
val price: String, | ||
@SerialName("transactionCount") | ||
val transactionCount: String, | ||
@SerialName("isScrap") | ||
val isScrap: Boolean, | ||
@SerialName("isFast") | ||
val isFast: Boolean, | ||
@SerialName("isFreeDeliver") | ||
val isFreeDeliver: Boolean, | ||
@SerialName("isSave") | ||
val isSave: Boolean, | ||
@SerialName("isCoupon") | ||
val isCoupon: Boolean, | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,20 @@ | ||
package org.sopt.kream.data.service | ||
|
||
import org.sopt.kream.data.model.response.ResponseRecommendProductDto | ||
import org.sopt.kream.data.model.response.ResponseSearchProductDto | ||
import org.sopt.kream.util.base.BaseResponse | ||
import retrofit2.http.GET | ||
import retrofit2.http.Header | ||
import retrofit2.http.Query | ||
|
||
interface ProductService { | ||
@GET("product") | ||
suspend fun getSearchProduct( | ||
@Query("findName") findName: String, | ||
): BaseResponse<ResponseSearchProductDto> | ||
|
||
@GET("product/recommend") | ||
suspend fun getRecommendProduct( | ||
@Header("memberId") memberId: Int, | ||
): BaseResponse<ResponseRecommendProductDto> | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package org.sopt.kream.domain.model | ||
|
||
import androidx.annotation.DrawableRes | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Domain Layer는 순수 코틀린 파일만 있어야 합니다 (다른 라이브러리에 의존성 X) 이런 식으로 구현하면 androix 라이브러리에 의존성이 있는 상태가 되니 해당 파일은 presentation 으로 이동시키는 게 클린 아키텍처에 더 부합 할 것 같숩니당! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 헉 그렇군요..!! 감사합니다😻 |
||
|
||
data class InstagramModel( | ||
@DrawableRes val image: Int, | ||
val id: String, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package org.sopt.kream.domain.model | ||
|
||
data class RecommendForYouProductModel( | ||
val thumbnailUrl: String, | ||
val brandTitle: String, | ||
val engTitle: String, | ||
val price: String, | ||
val transactionCount: String, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package org.sopt.kream.domain.model | ||
|
||
data class RecommendJustDroppedProductModel( | ||
val thumbnailUrl: String, | ||
val brandTitle: String, | ||
val engTitle: String, | ||
val price: String, | ||
val transactionCount: String, | ||
val isScrap: Boolean, | ||
val isFast: Boolean, | ||
val isFreeDeliver: Boolean, | ||
val isSave: Boolean, | ||
val isCoupon: Boolean, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package org.sopt.kream.domain.model | ||
|
||
data class RecommendProductModel( | ||
val recommendForYouProducts: List<RecommendForYouProductModel>, | ||
val recommendJustDroppedProducts: List<RecommendJustDroppedProductModel>, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,10 @@ | ||
package org.sopt.kream.domain.repository | ||
|
||
import org.sopt.kream.domain.model.RecommendProductModel | ||
import org.sopt.kream.domain.model.SearchProductModel | ||
|
||
interface ProductRepository { | ||
suspend fun getSearchProduct(findName: String): Result<SearchProductModel> | ||
|
||
suspend fun getRecommendProduct(memberId: Int): Result<RecommendProductModel> | ||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 뷰홀더랑 네이밍 맞추는 편이 좋을 것 같습니다 ~ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 헉 네이밍 바꾸면서 이걸 놓쳤네요😅 감사합니다!! |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package org.sopt.kream.presentation.ui.main.home.recommend | ||
|
||
import android.view.LayoutInflater | ||
import android.view.ViewGroup | ||
import androidx.recyclerview.widget.RecyclerView | ||
import org.sopt.kream.databinding.ItemRecommendAdBinding | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 시간적 여유가 있으면 ListAdapter + DiffUtil 사용해 보는 걸 추천합니다 (사실 이거 가져가기로 했었어서,,, 적용했으면 좋겠습니당) |
||
class RecommendAdViewPagerAdapter(private val data: List<Int>) : RecyclerView.Adapter<RecommendAdvertisementViewHolder>() { | ||
private val item = data | ||
|
||
override fun getItemCount(): Int = item.size | ||
|
||
override fun onBindViewHolder( | ||
holder: RecommendAdvertisementViewHolder, | ||
position: Int, | ||
) { | ||
holder.onBind(item[position]) | ||
} | ||
|
||
override fun onCreateViewHolder( | ||
parent: ViewGroup, | ||
viewType: Int, | ||
): RecommendAdvertisementViewHolder { | ||
val binding = ItemRecommendAdBinding.inflate(LayoutInflater.from(parent.context), parent, false) | ||
return RecommendAdvertisementViewHolder(binding) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package org.sopt.kream.presentation.ui.main.home.recommend | ||
|
||
import androidx.recyclerview.widget.RecyclerView | ||
import org.sopt.kream.databinding.ItemRecommendAdBinding | ||
|
||
class RecommendAdvertisementViewHolder( | ||
private val binding: ItemRecommendAdBinding, | ||
) : RecyclerView.ViewHolder(binding.root) { | ||
fun onBind( | ||
item: Int, | ||
) { | ||
with(binding) { | ||
ivRecommendAd.setImageResource(item) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,29 @@ | ||||||
package org.sopt.kream.presentation.ui.main.home.recommend | ||||||
|
||||||
import android.view.LayoutInflater | ||||||
import android.view.ViewGroup | ||||||
import androidx.recyclerview.widget.RecyclerView | ||||||
import org.sopt.kream.databinding.ItemRecommendCircleMenuBinding | ||||||
import org.sopt.kream.presentation.ui.type.RecommendCircleMenuType | ||||||
import kotlin.enums.EnumEntries | ||||||
|
||||||
class RecommendCircleMenuAdapter(private val list: EnumEntries<RecommendCircleMenuType>) : RecyclerView.Adapter<RecommendCircleMenuViewHolder>() { | ||||||
private val item = list | ||||||
|
||||||
override fun onCreateViewHolder( | ||||||
parent: ViewGroup, | ||||||
viewType: Int, | ||||||
): RecommendCircleMenuViewHolder { | ||||||
val binding = ItemRecommendCircleMenuBinding.inflate(LayoutInflater.from(parent.context), parent, false) | ||||||
return RecommendCircleMenuViewHolder(binding) | ||||||
} | ||||||
|
||||||
override fun onBindViewHolder( | ||||||
holder: RecommendCircleMenuViewHolder, | ||||||
position: Int, | ||||||
) { | ||||||
holder.onBind(item.get(position).menu) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
그리고 이거 이미지 디쟌 측에서 추가해주시면 menu만 넘기는 게 아니라 그냥 아이템 객체 자체를 넘겨야 할 것 같숩니다 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 넵~~!! |
||||||
} | ||||||
|
||||||
override fun getItemCount(): Int = list.size | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package org.sopt.kream.presentation.ui.main.home.recommend | ||
|
||
import androidx.recyclerview.widget.RecyclerView | ||
import org.sopt.kream.databinding.ItemRecommendCircleMenuBinding | ||
|
||
class RecommendCircleMenuViewHolder( | ||
private val binding: ItemRecommendCircleMenuBinding, | ||
) : RecyclerView.ViewHolder(binding.root) { | ||
fun onBind( | ||
item: String, | ||
) { | ||
with(binding) { | ||
tvCircleMenuTitle.text = item | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package org.sopt.kream.presentation.ui.main.home.recommend | ||
|
||
import android.view.LayoutInflater | ||
import android.view.ViewGroup | ||
import androidx.recyclerview.widget.ListAdapter | ||
import org.sopt.kream.databinding.ItemRecommendForYouProductBinding | ||
import org.sopt.kream.domain.model.RecommendForYouProductModel | ||
import org.sopt.kream.util.view.ItemDiffCallback | ||
|
||
class RecommendForYouAdapter( | ||
private val navigateToProductDetail: (Int) -> Unit, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 왁 화면 연결까지 야무지네요 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 헤헿 감사합니다❤️ |
||
private val page: Int, | ||
) : ListAdapter< | ||
RecommendForYouProductModel, | ||
RecommendForYouViewHolder, | ||
>( | ||
ItemDiffCallback<RecommendForYouProductModel>( | ||
onContentsTheSame = { old, new -> old == new }, | ||
onItemsTheSame = { old, new -> old.engTitle == new.engTitle }, | ||
Comment on lines
+14
to
+19
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오 여기는 리스트 어댑터를 사용하셨네요? 안 사용하신 부분도 적용해주시면 좋을 것 같아요! |
||
), | ||
) { | ||
override fun onCreateViewHolder( | ||
parent: ViewGroup, | ||
viewType: Int, | ||
): RecommendForYouViewHolder = | ||
RecommendForYouViewHolder( | ||
ItemRecommendForYouProductBinding.inflate( | ||
LayoutInflater.from(parent.context), | ||
parent, | ||
false, | ||
), | ||
navigateToProductDetail, | ||
) | ||
|
||
override fun onBindViewHolder( | ||
holder: RecommendForYouViewHolder, | ||
position: Int, | ||
) { | ||
holder.onBind( | ||
recommendForYouProductModel = currentList[page * 6 + position], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이거 이런 식으로 설정한 이유가 뭔가요? 애초에 어댑터에 값을 넣을 때 6개씩 쪼개서 리스트를 만들어두고 그 리스트를 어댑터에 넣어주는 편이 좋을 것 같습니다 |
||
position = position, | ||
) | ||
} | ||
|
||
override fun getItemCount(): Int = 6 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 요거 따로 설정해 주시지 않아도 돼요 |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package org.sopt.kream.presentation.ui.main.home.recommend | ||
|
||
import android.view.View | ||
import androidx.recyclerview.widget.RecyclerView | ||
import coil.load | ||
import org.sopt.kream.databinding.ItemRecommendForYouProductBinding | ||
import org.sopt.kream.domain.model.RecommendForYouProductModel | ||
|
||
class RecommendForYouViewHolder( | ||
private val binding: ItemRecommendForYouProductBinding, | ||
private val navigateToProductDetail: (Int) -> Unit, | ||
) : RecyclerView.ViewHolder(binding.root) { | ||
fun onBind( | ||
recommendForYouProductModel: RecommendForYouProductModel, | ||
position: Int, | ||
) { | ||
with(binding) { | ||
ivForYou.load(recommendForYouProductModel.thumbnailUrl) | ||
tvForYouBrand.text = recommendForYouProductModel.brandTitle | ||
tvForYouProduct.text = recommendForYouProductModel.engTitle | ||
tvForYouPrice.text = recommendForYouProductModel.price | ||
tvForYouTransaction.text = recommendForYouProductModel.transactionCount | ||
tvForYouSee.visibility = View.INVISIBLE | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
개인적으로는 it을 그대로 사용하는 것보다 네이밍을 해주고 사용하는 것을 선호하는 편이지만 갠취니까 그냥 참고만 해주세요 ~