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 5c0e478f..6a189dfd 100644 --- a/presentation/src/main/java/co/orange/presentation/detail/DetailActivity.kt +++ b/presentation/src/main/java/co/orange/presentation/detail/DetailActivity.kt @@ -3,6 +3,7 @@ package co.orange.presentation.detail import android.content.Context import android.content.Intent import android.graphics.Paint +import android.net.Uri import android.os.Bundle import androidx.activity.viewModels import androidx.core.view.isVisible @@ -20,6 +21,9 @@ import kr.genti.presentation.databinding.ActivityDetailBinding @AndroidEntryPoint class DetailActivity : BaseActivity(R.layout.activity_detail) { private val viewModel by viewModels() + + private var optionBottomSheet: OptionBottomSheet? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -38,8 +42,11 @@ class DetailActivity : BaseActivity(R.layout.activity_det } private fun initDetailViewBtnListener() { - // TODO - binding.btnDetailView.setOnSingleClickListener { } + binding.btnDetailView.setOnSingleClickListener { + if (viewModel.mockProduct.infoUrl.isNotEmpty()) { + startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(viewModel.mockProduct.infoUrl))) + } + } } private fun initLikeBtnListener() { @@ -48,8 +55,10 @@ class DetailActivity : BaseActivity(R.layout.activity_det } private fun initPurchaseBtnListener() { - // TODO - binding.btnPurchase.setOnSingleClickListener { } + binding.btnPurchase.setOnSingleClickListener { + optionBottomSheet = OptionBottomSheet() + optionBottomSheet?.show(supportFragmentManager, BOTTOM_SHEET_OPTION) + } } private fun getIntentInfo() { @@ -80,11 +89,19 @@ class DetailActivity : BaseActivity(R.layout.activity_det } } + override fun onDestroy() { + super.onDestroy() + + optionBottomSheet = null + } + companion object { private const val EXTRA_PRODUCT_URL = "EXTRA_PRODUCT_URL" private const val EXTRA_ORIGIN_PRICE = "EXTRA_ORIGIN_PRICE" private const val EXTRA_SALE_PRICE = "EXTRA_SALE_PRICE" + private const val BOTTOM_SHEET_OPTION = "BOTTOM_SHEET_OPTION" + @JvmStatic fun createIntent( context: Context, 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 c4a68928..a7502ff9 100644 --- a/presentation/src/main/java/co/orange/presentation/detail/DetailViewModel.kt +++ b/presentation/src/main/java/co/orange/presentation/detail/DetailViewModel.kt @@ -1,6 +1,7 @@ package co.orange.presentation.detail import androidx.lifecycle.ViewModel +import co.orange.domain.entity.response.OptionModel import co.orange.domain.entity.response.ProductDetailModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @@ -20,6 +21,11 @@ constructor( 12, "", 123, - listOf() + listOf( + OptionModel(1,"옵션 1", listOf()), + OptionModel(2,"옵션 2", listOf()), + OptionModel(3,"옵션 3", listOf()), + OptionModel(4,"옵션 4", listOf()) + ) ) } \ No newline at end of file diff --git a/presentation/src/main/java/co/orange/presentation/detail/OptionAdapter.kt b/presentation/src/main/java/co/orange/presentation/detail/OptionAdapter.kt new file mode 100644 index 00000000..189a4ece --- /dev/null +++ b/presentation/src/main/java/co/orange/presentation/detail/OptionAdapter.kt @@ -0,0 +1,38 @@ +package co.orange.presentation.detail + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.ListAdapter +import co.orange.domain.entity.response.OptionModel +import kr.genti.core.util.ItemDiffCallback +import kr.genti.presentation.databinding.ItemOptionBinding + +class OptionAdapter( + private val itemClick: (Int, Long) -> Unit, +) : ListAdapter(diffUtil) { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OptionViewHolder { + val inflater by lazy { LayoutInflater.from(parent.context) } + val binding: ItemOptionBinding = + ItemOptionBinding.inflate(inflater, parent, false) + return OptionViewHolder(binding, itemClick) + } + + override fun onBindViewHolder(holder: OptionViewHolder, position: Int) { + val item = getItem(position) ?: return + holder.onBind(item, position) + } + + fun addList(newItems: List) { + val currentItems = currentList.toMutableList() + currentItems.addAll(newItems) + submitList(currentItems) + } + + companion object { + private val diffUtil = ItemDiffCallback( + onItemsTheSame = { old, new -> old.optionId == new.optionId }, + onContentsTheSame = { old, new -> old == new }, + ) + } +} \ No newline at end of file diff --git a/presentation/src/main/java/co/orange/presentation/detail/OptionBottomSheet.kt b/presentation/src/main/java/co/orange/presentation/detail/OptionBottomSheet.kt new file mode 100644 index 00000000..60159b8d --- /dev/null +++ b/presentation/src/main/java/co/orange/presentation/detail/OptionBottomSheet.kt @@ -0,0 +1,67 @@ +package co.orange.presentation.detail + +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import android.view.View +import androidx.fragment.app.activityViewModels +import co.orange.presentation.main.home.HomeProductViewHolder.Companion.OVER_999 +import kr.genti.core.base.BaseBottomSheet +import kr.genti.core.extension.setOnSingleClickListener +import kr.genti.presentation.R +import kr.genti.presentation.databinding.BottomSheetOptionBinding + +class OptionBottomSheet : + BaseBottomSheet(R.layout.bottom_sheet_option) { + + private val viewModel by activityViewModels() + + private var _adapter: OptionAdapter? = null + private val adapter + get() = requireNotNull(_adapter) { getString(R.string.adapter_not_initialized_error_msg) } + + override fun onStart() { + super.onStart() + dialog?.window?.setBackgroundDrawableResource(R.color.transparent) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + initDetailViewBtnListener() + initAdapter() + setInterestCount() + setOptionData() + } + + private fun initDetailViewBtnListener() { + binding.btnDetailView.setOnSingleClickListener { + if (viewModel.mockProduct.infoUrl.isNotEmpty()) { + startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(viewModel.mockProduct.infoUrl))) + } + } + } + + private fun initAdapter() { + _adapter = OptionAdapter( + itemClick = ::initItemClickListener, + ) + binding.rvOption.adapter = adapter + } + + private fun initItemClickListener(position: Int, optionId: Long) { + // TODO + } + + private fun setInterestCount() { + binding.tvOptionLike.text = if (viewModel.mockProduct.interestCount < 1000) { + viewModel.mockProduct.interestCount.toString() + } else { + OVER_999 + } + } + + private fun setOptionData() { + adapter.addList(viewModel.mockProduct.optionList) + } +} \ 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 new file mode 100644 index 00000000..240c81a0 --- /dev/null +++ b/presentation/src/main/java/co/orange/presentation/detail/OptionViewHolder.kt @@ -0,0 +1,22 @@ +package co.orange.presentation.detail + +import androidx.recyclerview.widget.RecyclerView +import co.orange.domain.entity.response.OptionModel +import kr.genti.core.extension.setOnSingleClickListener +import kr.genti.presentation.databinding.ItemOptionBinding + +class OptionViewHolder( + val binding: ItemOptionBinding, + private val itemClick: (Int, Long) -> Unit, +) : RecyclerView.ViewHolder(binding.root) { + + fun onBind(item: OptionModel, position: Int) { + // TODO: 수정된 UI 대응 + with(binding) { + tvOptionItemTitle.text = item.type + root.setOnSingleClickListener { + itemClick(position, item.optionId) + } + } + } +} \ No newline at end of file diff --git a/presentation/src/main/res/drawable/ic_check_unselected.xml b/presentation/src/main/res/drawable/ic_check_unselected.xml new file mode 100644 index 00000000..f159ae32 --- /dev/null +++ b/presentation/src/main/res/drawable/ic_check_unselected.xml @@ -0,0 +1,9 @@ + + + diff --git a/presentation/src/main/res/drawable/shape_gray4_fill_100_rect.xml b/presentation/src/main/res/drawable/shape_gray4_fill_100_rect.xml new file mode 100644 index 00000000..54cd92e8 --- /dev/null +++ b/presentation/src/main/res/drawable/shape_gray4_fill_100_rect.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/presentation/src/main/res/drawable/shape_white_fill_top20_rect.xml b/presentation/src/main/res/drawable/shape_white_fill_top20_rect.xml new file mode 100644 index 00000000..0b47fa4f --- /dev/null +++ b/presentation/src/main/res/drawable/shape_white_fill_top20_rect.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/presentation/src/main/res/layout/bottom_sheet_option.xml b/presentation/src/main/res/layout/bottom_sheet_option.xml new file mode 100644 index 00000000..be3c0890 --- /dev/null +++ b/presentation/src/main/res/layout/bottom_sheet_option.xml @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/presentation/src/main/res/layout/item_option.xml b/presentation/src/main/res/layout/item_option.xml new file mode 100644 index 00000000..99d2a2ef --- /dev/null +++ b/presentation/src/main/res/layout/item_option.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml index 7eafee7d..ec54e386 100644 --- a/presentation/src/main/res/values/strings.xml +++ b/presentation/src/main/res/values/strings.xml @@ -29,4 +29,7 @@ 이 상품에 대한 자세한 정보를 보고 싶다면? 구매하기 + + 원하는 옵션을 선택해주세요 + *각인 옵션은 사용할 수 없습니다. \ No newline at end of file diff --git a/presentation/src/main/res/values/styles.xml b/presentation/src/main/res/values/styles.xml new file mode 100644 index 00000000..166dd24d --- /dev/null +++ b/presentation/src/main/res/values/styles.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/presentation/src/main/res/values/themes.xml b/presentation/src/main/res/values/themes.xml index e1395fcd..50b7cd58 100644 --- a/presentation/src/main/res/values/themes.xml +++ b/presentation/src/main/res/values/themes.xml @@ -9,6 +9,9 @@ @color/gray_3 + + @style/AppBottomSheetDialogTheme +