-
Notifications
You must be signed in to change notification settings - Fork 1
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] 상품 상세 뷰 구현 #27
Merged
Merged
Changes from 18 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
8555363
[feat] #26 ProductDetailButton component 구현
jihyunniiii ac2ebdb
[feat] #26 상품 상세 뷰 구현을 위한 strings.xml 리소스 추가
jihyunniiii 8442fab
[feat] #26 네이밍 변경
jihyunniiii 2586a33
[feat] #26 상품 상세 뷰 상하단 바 구현
jihyunniiii 9c1967e
[feat] #20 상품 상세 뷰 UI 구현
jihyunniiii 906e9ea
[feat] #20 세부 상품 조회 API 연동
jihyunniiii 1267cc3
[feat] #20 세부 상품 조회 API 연동을 위한 Model 생성
jihyunniiii 775e4c6
[chore] #20 스타일 string 변경
jihyunniiii 98d630a
[feat] #20 product detail info 리사이클러뷰 구현
jihyunniiii 7464bfb
[feat] #20 product detail info 리사이클러뷰 아이템 구현
jihyunniiii 7fcd72b
[feat] #20 product detail style 구현
jihyunniiii 6b5c5e5
[chore] #20 레이아웃 수정
jihyunniiii 34d358e
[feat] #20 뒤로가기 구현
jihyunniiii d5226cc
[chore] #20 스타일 레이아웃 수정
jihyunniiii 79cade0
[chore] #20 ktlintFormat
jihyunniiii 8c9898c
[feat] #20 스타일 없을 경우에 대한 분기처리
jihyunniiii 2d00a80
[chore] #20 ktlintFormat
jihyunniiii fcffe05
[chore] #26 더보기 text 속성 추가
jihyunniiii 5f3503f
Merge branch 'develop' into feat-product-detail-view
jihyunniiii File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
3 changes: 3 additions & 0 deletions
3
app/src/main/java/org/sopt/kream/data/datasource/ProductRemoteDataSource.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.ResponseProductDetailDto | ||
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 getProductDetail(productId: Int): BaseResponse<ResponseProductDetailDto> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
app/src/main/java/org/sopt/kream/data/mapper/ResponseProductDetailDtoMapper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package org.sopt.kream.data.mapper | ||
|
||
import org.sopt.kream.data.model.response.ResponseProductDetailDto | ||
import org.sopt.kream.domain.model.ProductDetailModel | ||
|
||
fun ResponseProductDetailDto.toProductDetailModel() = | ||
ProductDetailModel( | ||
thumbnailUrl = this.thumbnailUrl, | ||
price = this.price, | ||
engTitle = this.engTitle, | ||
title = this.title, | ||
recentPrice = this.recentPrice, | ||
variablePrice = this.variablePrice, | ||
variablePercent = this.variablePercent, | ||
releasePrice = this.releasePrice, | ||
modelNumber = this.modelNumber, | ||
releaseDate = this.releaseDate, | ||
styleCount = this.styleCount, | ||
styles = | ||
this.styles.map { responseProductDetailStyleDto -> | ||
responseProductDetailStyleDto.toProductDetailStyleModel() | ||
}, | ||
isScrap = this.isScrap, | ||
scrapCount = this.scrapCount, | ||
cellPrice = this.cellPrice, | ||
) |
10 changes: 10 additions & 0 deletions
10
app/src/main/java/org/sopt/kream/data/mapper/ResponseProductDetailStyleDtoMapper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.ResponseProductDetailDto.ResponseProductDetailStyleDto | ||
import org.sopt.kream.domain.model.ProductDetailStyleModel | ||
|
||
fun ResponseProductDetailStyleDto.toProductDetailStyleModel() = | ||
ProductDetailStyleModel( | ||
imageUrl = this.imageUrl, | ||
isVideo = this.isVideo, | ||
) |
46 changes: 46 additions & 0 deletions
46
app/src/main/java/org/sopt/kream/data/model/response/ResponseProductDetailDto.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package org.sopt.kream.data.model.response | ||
|
||
import kotlinx.serialization.SerialName | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class ResponseProductDetailDto( | ||
@SerialName("thumbnailUrl") | ||
val thumbnailUrl: String, | ||
@SerialName("price") | ||
val price: String, | ||
@SerialName("engTitle") | ||
val engTitle: String, | ||
@SerialName("title") | ||
val title: String, | ||
@SerialName("recentPrice") | ||
val recentPrice: String, | ||
@SerialName("variablePrice") | ||
val variablePrice: String, | ||
@SerialName("variablePercent") | ||
val variablePercent: String, | ||
@SerialName("releasePrice") | ||
val releasePrice: String, | ||
@SerialName("modelNumber") | ||
val modelNumber: String, | ||
@SerialName("releaseDate") | ||
val releaseDate: String, | ||
@SerialName("styleCount") | ||
val styleCount: String, | ||
@SerialName("styles") | ||
val styles: List<ResponseProductDetailStyleDto>, | ||
@SerialName("isScrap") | ||
val isScrap: Boolean, | ||
@SerialName("scrapCount") | ||
val scrapCount: String, | ||
@SerialName("cellPrice") | ||
val cellPrice: String, | ||
) { | ||
@Serializable | ||
data class ResponseProductDetailStyleDto( | ||
@SerialName("imageUrl") | ||
val imageUrl: String, | ||
@SerialName("isVideo") | ||
val isVideo: Boolean, | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
app/src/main/java/org/sopt/kream/data/service/ProductService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,26 @@ | ||
package org.sopt.kream.data.service | ||
|
||
import org.sopt.kream.data.model.response.ResponseProductDetailDto | ||
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.Path | ||
import retrofit2.http.Query | ||
|
||
interface ProductService { | ||
@GET("product") | ||
suspend fun getSearchProduct( | ||
@Query("findName") findName: String, | ||
): BaseResponse<ResponseSearchProductDto> | ||
|
||
@GET("product/{productId}") | ||
suspend fun getProductDetail( | ||
@Header("memberId") memberId: Int = MEMBER_ID, | ||
@Path("productId") productId: Int, | ||
): BaseResponse<ResponseProductDetailDto> | ||
|
||
companion object { | ||
const val MEMBER_ID = 1 | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
app/src/main/java/org/sopt/kream/domain/model/ProductDetailModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package org.sopt.kream.domain.model | ||
|
||
data class ProductDetailModel( | ||
val thumbnailUrl: String, | ||
val price: String, | ||
val engTitle: String, | ||
val title: String, | ||
val recentPrice: String, | ||
val variablePrice: String, | ||
val variablePercent: String, | ||
val releasePrice: String, | ||
val modelNumber: String, | ||
val releaseDate: String, | ||
val styleCount: String, | ||
val styles: List<ProductDetailStyleModel>, | ||
val isScrap: Boolean, | ||
val scrapCount: String, | ||
val cellPrice: String, | ||
) |
6 changes: 6 additions & 0 deletions
6
app/src/main/java/org/sopt/kream/domain/model/ProductDetailStyleModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package org.sopt.kream.domain.model | ||
|
||
data class ProductDetailStyleModel( | ||
val imageUrl: String, | ||
val isVideo: Boolean, | ||
) |
3 changes: 3 additions & 0 deletions
3
app/src/main/java/org/sopt/kream/domain/repository/ProductRepository.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.ProductDetailModel | ||
import org.sopt.kream.domain.model.SearchProductModel | ||
|
||
interface ProductRepository { | ||
suspend fun getSearchProduct(findName: String): Result<SearchProductModel> | ||
|
||
suspend fun getProductDetail(productId: Int): Result<ProductDetailModel> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
app/src/main/java/org/sopt/kream/presentation/ui/model/ProductDetailInfo.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package org.sopt.kream.presentation.ui.model | ||
|
||
import org.sopt.kream.presentation.ui.type.ProductDetailInfoType | ||
|
||
data class ProductDetailInfo( | ||
val productDetailInfoType: ProductDetailInfoType, | ||
val content: String, | ||
val additionalContent: String? = null, | ||
) |
116 changes: 115 additions & 1 deletion
116
app/src/main/java/org/sopt/kream/presentation/ui/productdetail/ProductDetailFragment.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,120 @@ | ||
package org.sopt.kream.presentation.ui.productdetail | ||
|
||
import android.os.Bundle | ||
import android.view.View | ||
import androidx.fragment.app.viewModels | ||
import androidx.lifecycle.flowWithLifecycle | ||
import androidx.lifecycle.lifecycleScope | ||
import androidx.navigation.fragment.findNavController | ||
import coil.load | ||
import kotlinx.coroutines.flow.launchIn | ||
import kotlinx.coroutines.flow.onEach | ||
import org.sopt.kream.R | ||
import org.sopt.kream.databinding.FragmentProductDetailBinding | ||
import org.sopt.kream.presentation.common.ViewModelFactory | ||
import org.sopt.kream.presentation.ui.model.ProductDetailInfo | ||
import org.sopt.kream.presentation.ui.search.SearchFragment.Companion.PRODUCT_ID | ||
import org.sopt.kream.presentation.ui.type.ProductDetailButtonType | ||
import org.sopt.kream.presentation.ui.type.ProductDetailInfoType | ||
import org.sopt.kream.util.base.BindingFragment | ||
import org.sopt.kream.util.component.KreamProductDetailStyleImageView | ||
import org.sopt.kream.util.view.UiState | ||
|
||
class ProductDetailFragment : BindingFragment<FragmentProductDetailBinding>({ FragmentProductDetailBinding.inflate(it) }) | ||
class ProductDetailFragment : BindingFragment<FragmentProductDetailBinding>({ FragmentProductDetailBinding.inflate(it) }) { | ||
private val productDetailViewModel: ProductDetailViewModel by viewModels { ViewModelFactory() } | ||
private lateinit var productDetailInfoAdapter: ProductDetailInfoAdapter | ||
|
||
override fun onViewCreated( | ||
view: View, | ||
savedInstanceState: Bundle?, | ||
) { | ||
super.onViewCreated(view, savedInstanceState) | ||
|
||
productDetailViewModel.getProductDetail(getProductId() + 1) | ||
initLayout() | ||
initAdapter() | ||
setIvProductDetailBack() | ||
collectProductDetailState() | ||
} | ||
|
||
private fun initLayout() { | ||
with(binding) { | ||
btnProductDetailBottomPurchase.setProductDetailButtonType(ProductDetailButtonType.PURCHASE) | ||
btnProductDetailBottomSale.setProductDetailButtonType(ProductDetailButtonType.SALE) | ||
} | ||
} | ||
|
||
private fun initAdapter() { | ||
productDetailInfoAdapter = ProductDetailInfoAdapter() | ||
binding.rvProductDetail.adapter = productDetailInfoAdapter | ||
} | ||
|
||
private fun setIvProductDetailBack() { | ||
binding.ivProductDetailBack.setOnClickListener { | ||
findNavController().popBackStack() | ||
} | ||
} | ||
|
||
private fun collectProductDetailState() { | ||
productDetailViewModel.productDetailState.flowWithLifecycle(viewLifecycleOwner.lifecycle) | ||
.onEach { productDetailState -> | ||
when (productDetailState) { | ||
is UiState.Success -> { | ||
with(binding) { | ||
ivProductDetailThumbnail.load(productDetailState.data.thumbnailUrl) | ||
tvProductDetailPrice.text = productDetailState.data.price | ||
tvProductDetailEngTitle.text = productDetailState.data.engTitle | ||
tvProductDetailTitle.text = productDetailState.data.title | ||
tvProductDetailStyle.text = getString(R.string.product_style, productDetailState.data.styleCount) | ||
ivProductDetailBottomScrap.setImageResource(if (productDetailState.data.isScrap) R.drawable.ic_saved_1_on_24 else R.drawable.ic_saved_1_off_24) | ||
tvProductDetailBottomScrap.text = productDetailState.data.scrapCount | ||
btnProductDetailBottomPurchase.priceTextView.text = productDetailState.data.price | ||
btnProductDetailBottomSale.priceTextView.text = productDetailState.data.cellPrice | ||
|
||
val productDetailStyleList: List<KreamProductDetailStyleImageView> = listOf(ivProductDetailStyleFirst, ivProductDetailStyleSecond, ivProductDetailStyleThird, ivProductDetailStyleFourth, ivProductDetailStyleFifth, ivProductDetailStyleSixth, ivProductDetailStyleSeventh, ivProductDetailStyleEight, ivProductDetailStyleNinth) | ||
|
||
productDetailState.data.styles.onEachIndexed { index, productDetailStyleModel -> | ||
productDetailStyleList[index].setImageViewData(productDetailStyleModel = productDetailStyleModel, isLast = index == (productDetailState.data.styles.size - 1)) | ||
} | ||
|
||
if (productDetailState.data.styles.isEmpty()) { | ||
viewProductDetailDeliveryInfo.background = null | ||
tvProductDetailStyle.visibility = View.GONE | ||
layoutProductDetailStyleUpload.visibility = View.GONE | ||
tvProductDetailStyleMore.visibility = View.GONE | ||
productDetailStyleList.onEach { kreamProductDetailStyleImageView -> | ||
kreamProductDetailStyleImageView.visibility = View.GONE | ||
} | ||
} | ||
|
||
productDetailInfoAdapter.submitList( | ||
listOf( | ||
ProductDetailInfo( | ||
productDetailInfoType = ProductDetailInfoType.RECENT_PRICE, | ||
content = productDetailState.data.recentPrice, | ||
additionalContent = productDetailState.data.variablePrice + productDetailState.data.variablePercent, | ||
), | ||
ProductDetailInfo( | ||
productDetailInfoType = ProductDetailInfoType.RELEASE_PRICE, | ||
content = productDetailState.data.releasePrice, | ||
), | ||
ProductDetailInfo( | ||
productDetailInfoType = ProductDetailInfoType.MODEL_NUMBER, | ||
content = productDetailState.data.modelNumber, | ||
), | ||
ProductDetailInfo( | ||
productDetailInfoType = ProductDetailInfoType.RELEASE_DATE, | ||
content = productDetailState.data.releaseDate, | ||
), | ||
), | ||
) | ||
} | ||
} | ||
|
||
else -> Unit | ||
} | ||
}.launchIn(viewLifecycleOwner.lifecycleScope) | ||
} | ||
|
||
private fun getProductId(): Int = requireArguments().getInt(PRODUCT_ID) | ||
} |
35 changes: 35 additions & 0 deletions
35
app/src/main/java/org/sopt/kream/presentation/ui/productdetail/ProductDetailInfoAdapter.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package org.sopt.kream.presentation.ui.productdetail | ||
|
||
import android.view.LayoutInflater | ||
import android.view.ViewGroup | ||
import androidx.recyclerview.widget.ListAdapter | ||
import org.sopt.kream.databinding.ItemProductDetailInfoBinding | ||
import org.sopt.kream.presentation.ui.model.ProductDetailInfo | ||
import org.sopt.kream.util.view.ItemDiffCallback | ||
|
||
class ProductDetailInfoAdapter() : ListAdapter<ProductDetailInfo, ProductDetailInfoViewHolder>( | ||
ItemDiffCallback<ProductDetailInfo>( | ||
onContentsTheSame = { old, new -> old == new }, | ||
onItemsTheSame = { old, new -> old.content == new.content }, | ||
), | ||
) { | ||
override fun onCreateViewHolder( | ||
parent: ViewGroup, | ||
viewType: Int, | ||
): ProductDetailInfoViewHolder = | ||
ProductDetailInfoViewHolder( | ||
ItemProductDetailInfoBinding.inflate( | ||
LayoutInflater.from(parent.context), | ||
parent, | ||
false, | ||
), | ||
parent.context, | ||
) | ||
|
||
override fun onBindViewHolder( | ||
holder: ProductDetailInfoViewHolder, | ||
position: Int, | ||
) { | ||
holder.onBind(currentList[position], currentList.size - 1 == position) | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
오 여기다가 상수로 선언해주니까 좋네요!!
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.
크크 상수화 잘 하면 가독성이 더 높아지는 것 같숨니다